diff --git a/CHANGELOG.md b/CHANGELOG.md
index a58d92a5ee..d1f8e9d090 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,25 @@
# Changelog
All changes to the project will be documented in this file.
-## [1.32.9] - not yet released
+## [1.32.12] - not released yet
+* Include constant values in `/typelookup` responses ([omnisharp-vscode#2857](https://github.com/OmniSharp/omnisharp-vscode/issues/2857), PR: [#1420](https://github.com/OmniSharp/omnisharp-roslyn/pull/1420))
+
+## [1.32.11] - 2019-02-27
+* Updated to Roslyn `3.0.0-beta4-19126-05` to match VS 16.0p4 ([#1413](https://github.com/OmniSharp/omnisharp-roslyn/issues/1413), PR: [#1414](https://github.com/OmniSharp/omnisharp-roslyn/pull/1414))
+* Added support for reading C# 8.0 `NullableContextOptions` from csproj files ([#1396](https://github.com/OmniSharp/omnisharp-roslyn/issues/1396), PR: [#1404](https://github.com/OmniSharp/omnisharp-roslyn/pull/1404))
+
+## [1.32.10] - 2019-01-25
+* Updated to Roslyn 3.0 to match [VS 2019](https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#VS2019_Preview2) (PR: [#1391](https://github.com/OmniSharp/omnisharp-roslyn/pull/1391))
+* Fixed shutdown event handling for LSP _(Contributed by [@LoneBoco](https://github.com/LoneBoco))_ ([#1113](https://github.com/OmniSharp/omnisharp-roslyn/issues/1113), PR: [#1345](https://github.com/OmniSharp/omnisharp-roslyn/pull/1345))
+
+## [1.32.9] - 2019-1-22
* Updated to Roslyn `2.11.0-beta1-final` and initial support for C# 8 (PR: [#1365](https://github.com/OmniSharp/omnisharp-roslyn/pull/1365))
* Incorporate *IndentSwitchCaseSectionWhenBlock* into OmniSharp's formatting options. This fixes the default formatting behavior, as the setting is set to *true* by default, and still allows users to disable it if needed. ([#1351](https://github.com/OmniSharp/omnisharp-roslyn/issues/1351), PR: [#1353](https://github.com/OmniSharp/omnisharp-roslyn/pull/1353))
* Removed unused `-stdio` flag from the `StdioCommandLineApplication` (PR: [#1362](https://github.com/OmniSharp/omnisharp-roslyn/pull/1362))
* Fixed finding references to operator overloads _(Contributed by [@SirIntruder](https://github.com/SirIntruder))_ (PR: [#1371](https://github.com/OmniSharp/omnisharp-roslyn/pull/1371))
+* Fixed a 1.29.0 regression that caused LSP not to work with `StdioCommandLineApplication` ([#1269](https://github.com/OmniSharp/omnisharp-roslyn/issues/1269), PR: [#1346](https://github.com/OmniSharp/omnisharp-roslyn/pull/1346))
+* Improved handling of files moving on disk (PR: [#1368](https://github.com/OmniSharp/omnisharp-roslyn/pull/1368))
+* Improved detection of MSBuild when multiple instances are available _(Contributed by [@johnnyasantoss ](https://github.com/johnnyasantoss))_ (PR: [#1349](https://github.com/OmniSharp/omnisharp-roslyn/pull/1349))
## [1.32.8] - 2018-11-14
* Fixed MSBuild discovery path (1.32.7 regression) (PR: [#1337](https://github.com/OmniSharp/omnisharp-roslyn/pull/1337))
diff --git a/NuGet.Config b/NuGet.Config
index ab6af752a0..0c203bfcab 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -4,5 +4,7 @@
+
+
diff --git a/OmniSharp.sln b/OmniSharp.sln
index 90b00b4ba6..16abae3947 100644
--- a/OmniSharp.sln
+++ b/OmniSharp.sln
@@ -9,6 +9,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
build.cake = build.cake
build.json = build.json
+ Directory.Build.props = Directory.Build.props
+ Directory.Build.targets = Directory.Build.targets
global.json = global.json
NuGet.Config = NuGet.Config
tools\packages.config = tools\packages.config
@@ -29,8 +31,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Stdio.Tests", "te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Abstractions", "src\OmniSharp.Abstractions\OmniSharp.Abstractions.csproj", "{0C54BE83-EF9E-4419-B654-A0760745BF80}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Plugins", "src\OmniSharp.Plugins\OmniSharp.Plugins.csproj", "{1C9AE254-6076-4EE6-80FD-B0AE4E16347D}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Roslyn.CSharp", "src\OmniSharp.Roslyn.CSharp\OmniSharp.Roslyn.CSharp.csproj", "{ED1A82CB-2741-45F5-A28B-7C36EFDF9746}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Roslyn", "src\OmniSharp.Roslyn\OmniSharp.Roslyn.csproj", "{4F5FC4AF-3977-4ECB-9B58-D16E8024BC97}"
@@ -73,6 +73,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Stdio.Driver", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Script.Tests", "tests\OmniSharp.Script.Tests\OmniSharp.Script.Tests.csproj", "{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniSharp.Shared", "src\OmniSharp.Shared\OmniSharp.Shared.csproj", "{9571E3FE-E742-44AC-9E1F-64156815B8E1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -131,18 +133,6 @@ Global
{0C54BE83-EF9E-4419-B654-A0760745BF80}.Release|x64.Build.0 = Release|Any CPU
{0C54BE83-EF9E-4419-B654-A0760745BF80}.Release|x86.ActiveCfg = Release|Any CPU
{0C54BE83-EF9E-4419-B654-A0760745BF80}.Release|x86.Build.0 = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|x64.ActiveCfg = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|x64.Build.0 = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|x86.ActiveCfg = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Debug|x86.Build.0 = Debug|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|Any CPU.Build.0 = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|x64.ActiveCfg = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|x64.Build.0 = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|x86.ActiveCfg = Release|Any CPU
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D}.Release|x86.Build.0 = Release|Any CPU
{ED1A82CB-2741-45F5-A28B-7C36EFDF9746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED1A82CB-2741-45F5-A28B-7C36EFDF9746}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED1A82CB-2741-45F5-A28B-7C36EFDF9746}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -395,6 +385,18 @@ Global
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x64.Build.0 = Release|Any CPU
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x86.ActiveCfg = Release|Any CPU
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x86.Build.0 = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|x64.Build.0 = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Debug|x86.Build.0 = Debug|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|x64.ActiveCfg = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|x64.Build.0 = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|x86.ActiveCfg = Release|Any CPU
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -404,7 +406,6 @@ Global
{A4F5FE6B-D3B4-4B63-A949-44E12AB8D535} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{AB5A975C-378B-45DC-AD69-50D808338AC2} = {35E025BF-BBB2-4FAC-9F4B-37CBA083EE47}
{0C54BE83-EF9E-4419-B654-A0760745BF80} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
- {1C9AE254-6076-4EE6-80FD-B0AE4E16347D} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{ED1A82CB-2741-45F5-A28B-7C36EFDF9746} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{4F5FC4AF-3977-4ECB-9B58-D16E8024BC97} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{9AF025CA-3706-401F-8D50-59FAD5AFE725} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
@@ -426,6 +427,7 @@ Global
{BC640CBF-F6E2-42EA-9D61-FB6E515AEA44} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{D2A78CEE-B278-476F-AF34-A7D6F792F973} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F} = {35E025BF-BBB2-4FAC-9F4B-37CBA083EE47}
+ {9571E3FE-E742-44AC-9E1F-64156815B8E1} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4DD725CE-B49A-4151-8B77-BB33FE88E46E}
diff --git a/README.md b/README.md
index 6980e04bcd..8e7017f852 100644
--- a/README.md
+++ b/README.md
@@ -10,10 +10,12 @@ OmniSharp-Roslyn is a .NET development platform based on [Roslyn](https://github
OmniSharp-Roslyn is built with the [.NET Core SDK](https://dot.net/) on Windows and [Mono](http://www.mono-project.com/) on OSX/Linux. It targets the __net461__ target framework. OmniSharp requires __mono__ (>=5.2.0) if it is run on a platform other than Windows.
-For Arch Linux users, need package [msbuild-stable](https://aur.archlinux.org/packages/msbuild-stable/) (>= 15.0)
+For Arch Linux users, need package [msbuild-stable](https://aur.archlinux.org/packages/msbuild-stable/) (>= 15.0).
In addition, if you need the HTTP interface and you want to run on Linux, you'll also need to make sure that you have [libuv](http://libuv.org) installed.
+See also https://github.com/OmniSharp/omnisharp-roslyn/issues/1202#issuecomment-421543905 .
+
## What's new
See our [change log](https://github.com/OmniSharp/omnisharp-roslyn/blob/master/CHANGELOG.md) for all of the updates.
diff --git a/build.cake b/build.cake
index c06bc0cd24..cb17aab3d8 100644
--- a/build.cake
+++ b/build.cake
@@ -48,7 +48,7 @@ bool AllowLegacyTests()
if (platform.IsLinux)
{
- var version = platform.Version.ToString();
+ var version = platform.Version?.ToString();
// Taken from https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/dotnet-install.sh
switch (platform.DistroName)
@@ -638,8 +638,6 @@ Task("Test")
// This is necessary to work around a Mono bug that is exasperated by xUnit.
DirectoryHelper.Copy($"{env.Folders.MonoMSBuildLib}", instanceFolder);
- DeleteUnnecessaryAssemblies(instanceFolder);
-
var runScript = CombinePaths(env.Folders.Mono, "run");
// By default, the run script launches OmniSharp. To launch our Mono runtime
@@ -655,25 +653,6 @@ Task("Test")
}
});
-///
-/// Delete assemblies that are included in our Mono package.
-///
-void DeleteUnnecessaryAssemblies(string folder)
-{
- FileHelper.Delete(CombinePaths(folder, "System.AppContext.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Numerics.Vectors.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Runtime.InteropServices.RuntimeInformation.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.ComponentModel.Primitives.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.ComponentModel.TypeConverter.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Console.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.IO.FileSystem.Primitives.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.IO.FileSystem.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Security.Cryptography.Encoding.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Security.Cryptography.Primitives.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Security.Cryptography.X509Certificates.dll"));
- FileHelper.Delete(CombinePaths(folder, "System.Threading.Thread.dll"));
-}
-
void CopyMonoBuild(BuildEnvironment env, string sourceFolder, string outputFolder)
{
DirectoryHelper.Copy(sourceFolder, outputFolder, copySubDirectories: false);
@@ -681,8 +660,6 @@ void CopyMonoBuild(BuildEnvironment env, string sourceFolder, string outputFolde
// Copy MSBuild runtime and libraries
DirectoryHelper.Copy($"{env.Folders.MSBuild}", CombinePaths(outputFolder, "msbuild"));
- // Included in Mono
- DeleteUnnecessaryAssemblies(outputFolder);
}
void CopyExtraDependencies(BuildEnvironment env, string outputFolder)
diff --git a/build.json b/build.json
index d3cf93632e..70307aa9eb 100644
--- a/build.json
+++ b/build.json
@@ -38,7 +38,8 @@
"CSharpAndFSharp",
"ProjectWithMismatchedFileName",
"SolutionWithSignedProject",
- "ProjectWithMultiTFMLib"
+ "ProjectWithMultiTFMLib",
+ "ExternAlias"
],
"LegacyTestAssets": [
"LegacyNUnitTestProject",
diff --git a/build/Packages.props b/build/Packages.props
index 58540edeab..8df4b99402 100644
--- a/build/Packages.props
+++ b/build/Packages.props
@@ -4,7 +4,7 @@
15.8.166
4.8.0
- 2.11.0-beta1-final
+ 3.0.0-beta4-19126-05
2.4.0
@@ -60,13 +60,17 @@
+
+
-
+
+
+
diff --git a/build/Settings.props b/build/Settings.props
index 443cce0df8..62b54e1687 100644
--- a/build/Settings.props
+++ b/build/Settings.props
@@ -2,7 +2,7 @@
- 7.2
+ 7.3
true
Debug
true
diff --git a/global.json b/global.json
index 4628116978..7455df8748 100644
--- a/global.json
+++ b/global.json
@@ -2,4 +2,4 @@
"sdk": {
"version": "2.1.301"
}
-}
+}
\ No newline at end of file
diff --git a/src/OmniSharp.Abstractions/Configuration.cs b/src/OmniSharp.Abstractions/Configuration.cs
index 172fdee5a9..c83160d21e 100644
--- a/src/OmniSharp.Abstractions/Configuration.cs
+++ b/src/OmniSharp.Abstractions/Configuration.cs
@@ -4,7 +4,7 @@ internal static class Configuration
{
public static bool ZeroBasedIndices = false;
- public const string RoslynVersion = "2.11.0.0";
+ public const string RoslynVersion = "3.0.0.0";
public const string RoslynPublicKeyToken = "31bf3856ad364e35";
public readonly static string RoslynFeatures = GetRoslynAssemblyFullName("Microsoft.CodeAnalysis.Features");
diff --git a/src/OmniSharp.Abstractions/Eventing/IEventEmitterExtensions.cs b/src/OmniSharp.Abstractions/Eventing/IEventEmitterExtensions.cs
index 0d093a4502..ef2d19fc37 100644
--- a/src/OmniSharp.Abstractions/Eventing/IEventEmitterExtensions.cs
+++ b/src/OmniSharp.Abstractions/Eventing/IEventEmitterExtensions.cs
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using OmniSharp.Models.Events;
+using OmniSharp;
+using OmniSharp.Models;
+using System.Linq;
namespace OmniSharp.Eventing
{
@@ -41,5 +44,24 @@ public static void UnresolvedDepdendencies(this IEventEmitter emitter, string pr
UnresolvedDependencies = unresolvedDependencies
});
}
+
+ public static void ProjectInformation(this IEventEmitter emitter,
+ HashedString projectGuid,
+ IEnumerable targetFrameworks,
+ IEnumerable references,
+ IEnumerable fileExtensions)
+ {
+ var projectConfiguration = new ProjectConfigurationMessage()
+ {
+ TargetFrameworks = targetFrameworks.Select(hashed => hashed.Value),
+ ProjectGuid = projectGuid.Value,
+ References = references.Select(hashed => hashed.Value),
+ FileExtensions = fileExtensions.Select(hashed => hashed.Value)
+ };
+
+ emitter.Emit(
+ EventTypes.ProjectConfiguration,
+ projectConfiguration);
+ }
}
}
diff --git a/src/OmniSharp.Abstractions/Models/Events/EventTypes.cs b/src/OmniSharp.Abstractions/Models/Events/EventTypes.cs
index ff36e5961f..8d68a21401 100644
--- a/src/OmniSharp.Abstractions/Models/Events/EventTypes.cs
+++ b/src/OmniSharp.Abstractions/Models/Events/EventTypes.cs
@@ -10,5 +10,6 @@ public static class EventTypes
public const string PackageRestoreStarted = nameof(PackageRestoreStarted);
public const string PackageRestoreFinished = nameof(PackageRestoreFinished);
public const string UnresolvedDependencies = nameof(UnresolvedDependencies);
+ public const string ProjectConfiguration = nameof(ProjectConfiguration);
}
}
diff --git a/src/OmniSharp.Abstractions/Models/Events/ProjectConfigurationMessage.cs b/src/OmniSharp.Abstractions/Models/Events/ProjectConfigurationMessage.cs
new file mode 100644
index 0000000000..df0707ba78
--- /dev/null
+++ b/src/OmniSharp.Abstractions/Models/Events/ProjectConfigurationMessage.cs
@@ -0,0 +1,13 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace OmniSharp.Models.Events
+{
+ public class ProjectConfigurationMessage
+ {
+ public string ProjectGuid { get; set; }
+ public IEnumerable TargetFrameworks { get; set; }
+ public IEnumerable References { get; set; }
+ public IEnumerable FileExtensions { get; set; }
+ }
+}
diff --git a/src/OmniSharp.Abstractions/Models/HashedString.cs b/src/OmniSharp.Abstractions/Models/HashedString.cs
new file mode 100644
index 0000000000..263054c5dc
--- /dev/null
+++ b/src/OmniSharp.Abstractions/Models/HashedString.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OmniSharp.Models
+{
+ public class HashedString
+ {
+ public HashedString(string value)
+ {
+ Value = value;
+ }
+
+ public string Value { get; }
+ }
+}
diff --git a/src/OmniSharp.Abstractions/Models/ZeroBasedIndexConverter.cs b/src/OmniSharp.Abstractions/Models/ZeroBasedIndexConverter.cs
index da1d16a0b5..4f23528635 100644
--- a/src/OmniSharp.Abstractions/Models/ZeroBasedIndexConverter.cs
+++ b/src/OmniSharp.Abstractions/Models/ZeroBasedIndexConverter.cs
@@ -5,7 +5,7 @@
namespace OmniSharp.Models
{
- public class ZeroBasedIndexConverter : JsonConverter
+ internal class ZeroBasedIndexConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
diff --git a/src/OmniSharp.Abstractions/OmniSharp.Abstractions.csproj b/src/OmniSharp.Abstractions/OmniSharp.Abstractions.csproj
index bdbde24a85..898109ffd8 100644
--- a/src/OmniSharp.Abstractions/OmniSharp.Abstractions.csproj
+++ b/src/OmniSharp.Abstractions/OmniSharp.Abstractions.csproj
@@ -8,9 +8,6 @@
-
-
-
diff --git a/src/OmniSharp.Plugins/Plugin.cs b/src/OmniSharp.Abstractions/Plugins/Plugin.cs
similarity index 100%
rename from src/OmniSharp.Plugins/Plugin.cs
rename to src/OmniSharp.Abstractions/Plugins/Plugin.cs
diff --git a/src/OmniSharp.Plugins/PluginAssemblies.cs b/src/OmniSharp.Abstractions/Plugins/PluginAssemblies.cs
similarity index 100%
rename from src/OmniSharp.Plugins/PluginAssemblies.cs
rename to src/OmniSharp.Abstractions/Plugins/PluginAssemblies.cs
diff --git a/src/OmniSharp.Plugins/PluginConfig.cs b/src/OmniSharp.Abstractions/Plugins/PluginConfig.cs
similarity index 100%
rename from src/OmniSharp.Plugins/PluginConfig.cs
rename to src/OmniSharp.Abstractions/Plugins/PluginConfig.cs
diff --git a/src/OmniSharp.Plugins/PluginRequest.cs b/src/OmniSharp.Abstractions/Plugins/PluginRequest.cs
similarity index 100%
rename from src/OmniSharp.Plugins/PluginRequest.cs
rename to src/OmniSharp.Abstractions/Plugins/PluginRequest.cs
diff --git a/src/OmniSharp.Plugins/PluginResponse.cs b/src/OmniSharp.Abstractions/Plugins/PluginResponse.cs
similarity index 100%
rename from src/OmniSharp.Plugins/PluginResponse.cs
rename to src/OmniSharp.Abstractions/Plugins/PluginResponse.cs
diff --git a/src/OmniSharp.Abstractions/Stdio/Services/ISharedTextWriter.cs b/src/OmniSharp.Abstractions/Services/ISharedTextWriter.cs
similarity index 82%
rename from src/OmniSharp.Abstractions/Stdio/Services/ISharedTextWriter.cs
rename to src/OmniSharp.Abstractions/Services/ISharedTextWriter.cs
index 6e73a59acc..e4bc56dffc 100644
--- a/src/OmniSharp.Abstractions/Stdio/Services/ISharedTextWriter.cs
+++ b/src/OmniSharp.Abstractions/Services/ISharedTextWriter.cs
@@ -1,6 +1,6 @@
using System.Threading.Tasks;
-namespace OmniSharp.Stdio.Services
+namespace OmniSharp.Services
{
public interface ISharedTextWriter
{
diff --git a/src/OmniSharp.Cake/OmniSharp.Cake.csproj b/src/OmniSharp.Cake/OmniSharp.Cake.csproj
index 2bd8c4b41b..693df59cc4 100644
--- a/src/OmniSharp.Cake/OmniSharp.Cake.csproj
+++ b/src/OmniSharp.Cake/OmniSharp.Cake.csproj
@@ -8,6 +8,7 @@
+
diff --git a/src/OmniSharp.DotNet/OmniSharp.DotNet.csproj b/src/OmniSharp.DotNet/OmniSharp.DotNet.csproj
index 92b1c303a4..5cb6a1084a 100644
--- a/src/OmniSharp.DotNet/OmniSharp.DotNet.csproj
+++ b/src/OmniSharp.DotNet/OmniSharp.DotNet.csproj
@@ -9,6 +9,7 @@
+
diff --git a/src/OmniSharp.Host/CompositionHostBuilder.cs b/src/OmniSharp.Host/CompositionHostBuilder.cs
index e3546c9487..a80af3f10a 100644
--- a/src/OmniSharp.Host/CompositionHostBuilder.cs
+++ b/src/OmniSharp.Host/CompositionHostBuilder.cs
@@ -11,6 +11,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OmniSharp.Eventing;
+using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Mef;
using OmniSharp.MSBuild.Discovery;
@@ -84,7 +85,7 @@ public CompositionHost Build()
}
var parts = _assemblies
- .Concat(new[] { typeof(OmniSharpWorkspace).GetTypeInfo().Assembly, typeof(IRequest).GetTypeInfo().Assembly })
+ .Concat(new[] { typeof(OmniSharpWorkspace).GetTypeInfo().Assembly, typeof(IRequest).GetTypeInfo().Assembly, typeof(FileSystemHelper).GetTypeInfo().Assembly })
.Distinct()
.SelectMany(a => SafeGetTypes(a))
.ToArray();
@@ -209,6 +210,7 @@ private static bool DependsOnOmniSharp(RuntimeLibrary runtimeLibrary)
foreach (var dependency in runtimeLibrary.Dependencies)
{
if (dependency.Name == "OmniSharp.Abstractions" ||
+ dependency.Name == "OmniSharp.Shared" ||
dependency.Name == "OmniSharp.Roslyn")
{
return true;
diff --git a/src/OmniSharp.Host/Endpoint/EndpointHandler.cs b/src/OmniSharp.Host/Endpoint/EndpointHandler.cs
index cd4cd97dc7..5426649783 100644
--- a/src/OmniSharp.Host/Endpoint/EndpointHandler.cs
+++ b/src/OmniSharp.Host/Endpoint/EndpointHandler.cs
@@ -14,7 +14,7 @@
using OmniSharp.Models;
using OmniSharp.Models.UpdateBuffer;
using OmniSharp.Plugins;
-using OmniSharp.Stdio.Protocol;
+using OmniSharp.Protocol;
namespace OmniSharp.Endpoint
{
diff --git a/src/OmniSharp.Host/Endpoint/GenericEndpointHandler.cs b/src/OmniSharp.Host/Endpoint/GenericEndpointHandler.cs
index b73e669a0d..1d0d821939 100644
--- a/src/OmniSharp.Host/Endpoint/GenericEndpointHandler.cs
+++ b/src/OmniSharp.Host/Endpoint/GenericEndpointHandler.cs
@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
-using OmniSharp.Stdio.Protocol;
+using OmniSharp.Protocol;
namespace OmniSharp.Endpoint
{
@@ -18,4 +18,4 @@ public override Task
-
-
+
+
+
+
diff --git a/src/OmniSharp.LanguageServerProtocol/RequestHandlerCollection.cs b/src/OmniSharp.LanguageServerProtocol/RequestHandlerCollection.cs
index 879eee3991..48e24ff35c 100644
--- a/src/OmniSharp.LanguageServerProtocol/RequestHandlerCollection.cs
+++ b/src/OmniSharp.LanguageServerProtocol/RequestHandlerCollection.cs
@@ -1,6 +1,6 @@
using System.Collections;
using System.Collections.Generic;
-using OmniSharp.Extensions.LanguageServer.Models;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Mef;
namespace OmniSharp.LanguageServerProtocol
@@ -29,4 +29,4 @@ IEnumerator IEnumerable.GetEnumerator()
return GetEnumerator();
}
}
-}
\ No newline at end of file
+}
diff --git a/src/OmniSharp.LanguageServerProtocol/RequestHandlers.cs b/src/OmniSharp.LanguageServerProtocol/RequestHandlers.cs
index ad083eee02..8348ff46eb 100644
--- a/src/OmniSharp.LanguageServerProtocol/RequestHandlers.cs
+++ b/src/OmniSharp.LanguageServerProtocol/RequestHandlers.cs
@@ -2,7 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using OmniSharp.Extensions.LanguageServer.Models;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Mef;
namespace OmniSharp.LanguageServerProtocol
diff --git a/src/OmniSharp.MSBuild/HashingAlgorithm.cs b/src/OmniSharp.MSBuild/HashingAlgorithm.cs
new file mode 100644
index 0000000000..05d097a67f
--- /dev/null
+++ b/src/OmniSharp.MSBuild/HashingAlgorithm.cs
@@ -0,0 +1,13 @@
+using OmniSharp.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace OmniSharp.MSBuild
+{
+ public interface IHasher
+ {
+ HashedString HashInput(string clearText);
+ }
+}
diff --git a/src/OmniSharp.MSBuild/Notification/ProjectLoadedEventArgs.cs b/src/OmniSharp.MSBuild/Notification/ProjectLoadedEventArgs.cs
index 9f166898c0..2e28794638 100644
--- a/src/OmniSharp.MSBuild/Notification/ProjectLoadedEventArgs.cs
+++ b/src/OmniSharp.MSBuild/Notification/ProjectLoadedEventArgs.cs
@@ -1,4 +1,5 @@
-using System.Collections.Immutable;
+using System.Collections.Generic;
+using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using OmniSharp.MSBuild.Logging;
using MSB = Microsoft.Build;
@@ -11,17 +12,26 @@ public class ProjectLoadedEventArgs
public MSB.Execution.ProjectInstance ProjectInstance { get; }
public ImmutableArray Diagnostics { get; }
public bool IsReload { get; }
+ public IEnumerable References { get; }
+ public ImmutableArray SourceFiles { get; }
+ public bool ProjectIdIsDefinedInSolution { get; }
public ProjectLoadedEventArgs(
ProjectId id,
MSB.Execution.ProjectInstance projectInstance,
ImmutableArray diagnostics,
- bool isReload)
+ bool isReload,
+ bool projectIdIsDefinedInSolution,
+ ImmutableArray sourceFiles,
+ IEnumerable references = null)
{
Id = id;
ProjectInstance = projectInstance;
Diagnostics = diagnostics;
IsReload = isReload;
+ ProjectIdIsDefinedInSolution = projectIdIsDefinedInSolution;
+ References = references;
+ SourceFiles = sourceFiles;
}
}
}
diff --git a/src/OmniSharp.MSBuild/ProjectFile/MetadataNames.cs b/src/OmniSharp.MSBuild/ProjectFile/MetadataNames.cs
index 74c5835fd8..56e54025e4 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/MetadataNames.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/MetadataNames.cs
@@ -8,5 +8,6 @@ internal static class MetadataNames
public const string OriginalItemSpec = nameof(OriginalItemSpec);
public const string ReferenceSourceTarget = nameof(ReferenceSourceTarget);
public const string Version = nameof(Version);
+ public const string Aliases = nameof(Aliases);
}
}
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
index efa43ca284..52e834ac23 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
@@ -32,6 +32,7 @@ private class ProjectData
public OutputKind OutputKind { get; }
public LanguageVersion LanguageVersion { get; }
+ public NullableContextOptions NullableContextOptions { get; }
public bool AllowUnsafeCode { get; }
public string DocumentationFile { get; }
public ImmutableArray PreprocessorSymbolNames { get; }
@@ -45,6 +46,7 @@ private class ProjectData
public ImmutableArray References { get; }
public ImmutableArray PackageReferences { get; }
public ImmutableArray Analyzers { get; }
+ public ImmutableDictionary ReferenceAliases { get; }
private ProjectData()
{
@@ -58,6 +60,7 @@ private ProjectData()
References = ImmutableArray.Empty;
PackageReferences = ImmutableArray.Empty;
Analyzers = ImmutableArray.Empty;
+ ReferenceAliases = ImmutableDictionary.Empty;
}
private ProjectData(
@@ -69,6 +72,7 @@ private ProjectData(
ImmutableArray targetFrameworks,
OutputKind outputKind,
LanguageVersion languageVersion,
+ NullableContextOptions nullableContextOptions,
bool allowUnsafeCode,
string documentationFile,
ImmutableArray preprocessorSymbolNames,
@@ -93,6 +97,7 @@ private ProjectData(
OutputKind = outputKind;
LanguageVersion = languageVersion;
+ NullableContextOptions = nullableContextOptions;
AllowUnsafeCode = allowUnsafeCode;
DocumentationFile = documentationFile;
PreprocessorSymbolNames = preprocessorSymbolNames.EmptyIfDefault();
@@ -111,6 +116,7 @@ private ProjectData(
ImmutableArray targetFrameworks,
OutputKind outputKind,
LanguageVersion languageVersion,
+ NullableContextOptions nullableContextOptions,
bool allowUnsafeCode,
string documentationFile,
ImmutableArray preprocessorSymbolNames,
@@ -121,9 +127,10 @@ private ProjectData(
ImmutableArray projectReferences,
ImmutableArray references,
ImmutableArray packageReferences,
- ImmutableArray analyzers)
+ ImmutableArray analyzers,
+ ImmutableDictionary referenceAliases)
: this(guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
- configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, allowUnsafeCode,
+ configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile)
{
SourceFiles = sourceFiles.EmptyIfDefault();
@@ -131,6 +138,7 @@ private ProjectData(
References = references.EmptyIfDefault();
PackageReferences = packageReferences.EmptyIfDefault();
Analyzers = analyzers.EmptyIfDefault();
+ ReferenceAliases = referenceAliases;
}
public static ProjectData Create(MSB.Evaluation.Project project)
@@ -158,6 +166,7 @@ public static ProjectData Create(MSB.Evaluation.Project project)
var languageVersion = PropertyConverter.ToLanguageVersion(project.GetPropertyValue(PropertyNames.LangVersion));
var allowUnsafeCode = PropertyConverter.ToBoolean(project.GetPropertyValue(PropertyNames.AllowUnsafeBlocks), defaultValue: false);
var outputKind = PropertyConverter.ToOutputKind(project.GetPropertyValue(PropertyNames.OutputType));
+ var nullableContextOptions = PropertyConverter.ToNullableContextOptions(project.GetPropertyValue(PropertyNames.NullableContextOptions));
var documentationFile = project.GetPropertyValue(PropertyNames.DocumentationFile);
var preprocessorSymbolNames = PropertyConverter.ToPreprocessorSymbolNames(project.GetPropertyValue(PropertyNames.DefineConstants));
var suppressedDiagnosticIds = PropertyConverter.ToSuppressedDiagnosticIds(project.GetPropertyValue(PropertyNames.NoWarn));
@@ -166,7 +175,7 @@ public static ProjectData Create(MSB.Evaluation.Project project)
return new ProjectData(
guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
- configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, allowUnsafeCode,
+ configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile);
}
@@ -195,6 +204,7 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
var languageVersion = PropertyConverter.ToLanguageVersion(projectInstance.GetPropertyValue(PropertyNames.LangVersion));
var allowUnsafeCode = PropertyConverter.ToBoolean(projectInstance.GetPropertyValue(PropertyNames.AllowUnsafeBlocks), defaultValue: false);
var outputKind = PropertyConverter.ToOutputKind(projectInstance.GetPropertyValue(PropertyNames.OutputType));
+ var nullableContextOptions = PropertyConverter.ToNullableContextOptions(projectInstance.GetPropertyValue(PropertyNames.NullableContextOptions));
var documentationFile = projectInstance.GetPropertyValue(PropertyNames.DocumentationFile);
var preprocessorSymbolNames = PropertyConverter.ToPreprocessorSymbolNames(projectInstance.GetPropertyValue(PropertyNames.DefineConstants));
var suppressedDiagnosticIds = PropertyConverter.ToSuppressedDiagnosticIds(projectInstance.GetPropertyValue(PropertyNames.NoWarn));
@@ -208,6 +218,7 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
projectInstance.GetItems(ItemNames.ProjectReference), filter: IsCSharpProject);
var references = ImmutableArray.CreateBuilder();
+ var referenceAliases = ImmutableDictionary.CreateBuilder();
foreach (var referencePathItem in projectInstance.GetItems(ItemNames.ReferencePath))
{
var referenceSourceTarget = referencePathItem.GetMetadataValue(MetadataNames.ReferenceSourceTarget);
@@ -233,17 +244,22 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
{
references.Add(fullPath);
}
+ var aliases = referencePathItem.GetMetadataValue(MetadataNames.Aliases);
+ if(!string.IsNullOrEmpty(aliases))
+ {
+ referenceAliases[referencePathItem.EvaluatedInclude] = aliases;
+ }
}
-
+
var packageReferences = GetPackageReferences(projectInstance.GetItems(ItemNames.PackageReference));
var analyzers = GetFullPaths(projectInstance.GetItems(ItemNames.Analyzer));
return new ProjectData(guid, name,
assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks,
- outputKind, languageVersion, allowUnsafeCode, documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds,
+ outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds,
signAssembly, assemblyOriginatorKeyFile,
- sourceFiles, projectReferences, references.ToImmutable(), packageReferences, analyzers);
+ sourceFiles, projectReferences, references.ToImmutable(), packageReferences, analyzers, referenceAliases.ToImmutableDictionary());
}
private static bool IsCSharpProject(string filePath)
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
index dc7d484a78..17f6a2f6a5 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
@@ -17,7 +17,7 @@ internal partial class ProjectFileInfo
public string FilePath { get; }
public string Directory { get; }
- public ProjectId Id { get; }
+ public ProjectId Id { get => ProjectIdInfo.Id; }
public Guid Guid => _data.Guid;
public string Name => _data.Name;
@@ -35,6 +35,7 @@ internal partial class ProjectFileInfo
public OutputKind OutputKind => _data.OutputKind;
public LanguageVersion LanguageVersion => _data.LanguageVersion;
+ public NullableContextOptions NullableContextOptions => _data.NullableContextOptions;
public bool AllowUnsafeCode => _data.AllowUnsafeCode;
public string DocumentationFile => _data.DocumentationFile;
public ImmutableArray PreprocessorSymbolNames => _data.PreprocessorSymbolNames;
@@ -48,13 +49,16 @@ internal partial class ProjectFileInfo
public ImmutableArray ProjectReferences => _data.ProjectReferences;
public ImmutableArray PackageReferences => _data.PackageReferences;
public ImmutableArray Analyzers => _data.Analyzers;
+ public ImmutableDictionary ReferenceAliases => _data.ReferenceAliases;
+
+ public ProjectIdInfo ProjectIdInfo { get; }
private ProjectFileInfo(
- ProjectId id,
+ ProjectIdInfo projectIdInfo,
string filePath,
ProjectData data)
{
- this.Id = id;
+ this.ProjectIdInfo = projectIdInfo;
this.FilePath = filePath;
this.Directory = Path.GetDirectoryName(filePath);
@@ -65,7 +69,7 @@ internal static ProjectFileInfo CreateEmpty(string filePath)
{
var id = ProjectId.CreateNewId(debugName: filePath);
- return new ProjectFileInfo(id, filePath, data: null);
+ return new ProjectFileInfo(new ProjectIdInfo(id, isDefinedInSolution:false), filePath, data: null);
}
internal static ProjectFileInfo CreateNoBuild(string filePath, ProjectLoader loader)
@@ -73,11 +77,13 @@ internal static ProjectFileInfo CreateNoBuild(string filePath, ProjectLoader loa
var id = ProjectId.CreateNewId(debugName: filePath);
var project = loader.EvaluateProjectFile(filePath);
var data = ProjectData.Create(project);
+ //we are not reading the solution here
+ var projectIdInfo = new ProjectIdInfo(id, isDefinedInSolution: false);
- return new ProjectFileInfo(id, filePath, data);
+ return new ProjectFileInfo(projectIdInfo, filePath, data);
}
- public static (ProjectFileInfo, ImmutableArray, ProjectLoadedEventArgs) Load(string filePath, ProjectLoader loader)
+ public static (ProjectFileInfo, ImmutableArray, ProjectLoadedEventArgs) Load(string filePath, ProjectIdInfo projectIdInfo, ProjectLoader loader)
{
if (!File.Exists(filePath))
{
@@ -90,10 +96,15 @@ public static (ProjectFileInfo, ImmutableArray, ProjectLoaded
return (null, diagnostics, null);
}
- var id = ProjectId.CreateNewId(debugName: filePath);
var data = ProjectData.Create(projectInstance);
- var projectFileInfo = new ProjectFileInfo(id, filePath, data);
- var eventArgs = new ProjectLoadedEventArgs(id, projectInstance, diagnostics, isReload: false);
+ var projectFileInfo = new ProjectFileInfo(projectIdInfo, filePath, data);
+ var eventArgs = new ProjectLoadedEventArgs(projectIdInfo.Id,
+ projectInstance,
+ diagnostics,
+ isReload: false,
+ projectIdInfo.IsDefinedInSolution,
+ projectFileInfo.SourceFiles,
+ data.References);
return (projectFileInfo, diagnostics, eventArgs);
}
@@ -107,8 +118,8 @@ public static (ProjectFileInfo, ImmutableArray, ProjectLoaded
}
var data = ProjectData.Create(projectInstance);
- var projectFileInfo = new ProjectFileInfo(Id, FilePath, data);
- var eventArgs = new ProjectLoadedEventArgs(Id, projectInstance, diagnostics, isReload: true);
+ var projectFileInfo = new ProjectFileInfo(ProjectIdInfo, FilePath, data);
+ var eventArgs = new ProjectLoadedEventArgs(Id, projectInstance, diagnostics, isReload: true, ProjectIdInfo.IsDefinedInSolution,data.References);
return (projectFileInfo, diagnostics, eventArgs);
}
diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs
index 7ad5386fa0..c6fec99f89 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs
@@ -18,6 +18,11 @@ public static CSharpCompilationOptions CreateCompilationOptions(this ProjectFile
result = result.WithAllowUnsafe(true);
}
+ if (projectFileInfo.NullableContextOptions != result.NullableContextOptions)
+ {
+ result = result.WithNullableContextOptions(projectFileInfo.NullableContextOptions);
+ }
+
result = result.WithSpecificDiagnosticOptions(CompilationOptionsHelper.GetDefaultSuppressedDiagnosticOptions(projectFileInfo.SuppressedDiagnosticIds));
if (projectFileInfo.SignAssembly && !string.IsNullOrEmpty(projectFileInfo.AssemblyOriginatorKeyFile))
diff --git a/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs b/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
index f095687cfa..efe7379bd4 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/PropertyConverter.cs
@@ -132,6 +132,19 @@ public static OutputKind ToOutputKind(string propertyValue)
}
}
+ public static NullableContextOptions ToNullableContextOptions(string propertyValue)
+ {
+ switch (propertyValue?.ToLowerInvariant())
+ {
+ case "disable": return NullableContextOptions.Disable;
+ case "enable": return NullableContextOptions.Enable;
+ case "safeonly": return NullableContextOptions.SafeOnly;
+ case "warnings": return NullableContextOptions.Warnings;
+ case "safeonlywarnings": return NullableContextOptions.SafeOnlyWarnings;
+ default: return NullableContextOptions.Disable;
+ }
+ }
+
public static VersionRange ToVersionRange(string propertyValue)
{
if (VersionRange.TryParse(propertyValue.Trim(), out var version))
diff --git a/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs b/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs
index 8aaab92371..26063e70ec 100644
--- a/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs
+++ b/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs
@@ -21,6 +21,7 @@ internal static class PropertyNames
public const string MSBuildExtensionsPath = nameof(MSBuildExtensionsPath);
public const string MSBuildSDKsPath = nameof(MSBuildSDKsPath);
public const string NoWarn = nameof(NoWarn);
+ public const string NullableContextOptions = nameof(NullableContextOptions);
public const string OutputPath = nameof(OutputPath);
public const string Platform = nameof(Platform);
public const string ProjectAssetsFile = nameof(ProjectAssetsFile);
diff --git a/src/OmniSharp.MSBuild/ProjectIdInfo.cs b/src/OmniSharp.MSBuild/ProjectIdInfo.cs
new file mode 100644
index 0000000000..b1a46a1b26
--- /dev/null
+++ b/src/OmniSharp.MSBuild/ProjectIdInfo.cs
@@ -0,0 +1,17 @@
+using System;
+using Microsoft.CodeAnalysis;
+
+namespace OmniSharp.MSBuild
+{
+ public class ProjectIdInfo
+ {
+ public ProjectIdInfo(ProjectId id, bool isDefinedInSolution)
+ {
+ Id = id ?? throw new ArgumentNullException(nameof(id));
+ IsDefinedInSolution = isDefinedInSolution;
+ }
+
+ public ProjectId Id { get; set; }
+ public bool IsDefinedInSolution { get; set; }
+ }
+}
diff --git a/src/OmniSharp.MSBuild/ProjectLoadListener.cs b/src/OmniSharp.MSBuild/ProjectLoadListener.cs
new file mode 100644
index 0000000000..c4aa6fe415
--- /dev/null
+++ b/src/OmniSharp.MSBuild/ProjectLoadListener.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Composition;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Execution;
+using Microsoft.Extensions.Logging;
+using OmniSharp.Eventing;
+using OmniSharp.Models;
+using OmniSharp.MSBuild.Notification;
+
+namespace OmniSharp.MSBuild
+{
+ [Export(typeof(IMSBuildEventSink))]
+ public class ProjectLoadListener : IMSBuildEventSink
+ {
+ internal const string TargetFramework = nameof(TargetFramework);
+ internal const string TargetFrameworkVersion = nameof(TargetFrameworkVersion);
+ internal const string TargetFrameworks = nameof(TargetFrameworks);
+ private const string MSBuildProjectFullPath = nameof(MSBuildProjectFullPath);
+ private readonly ILogger _logger;
+ private readonly IEventEmitter _eventEmitter;
+ private static readonly VsTfmAndFileExtHashingAlgorithm _tfmAndFileHashingAlgorithm = new VsTfmAndFileExtHashingAlgorithm();
+ private static readonly VsReferenceHashingAlgorithm _referenceHashingAlgorithm = new VsReferenceHashingAlgorithm();
+
+ [ImportingConstructor]
+ public ProjectLoadListener(ILoggerFactory loggerFactory, IEventEmitter eventEmitter)
+ {
+ _logger = loggerFactory.CreateLogger();
+ _eventEmitter = eventEmitter;
+ }
+
+ public void ProjectLoaded(ProjectLoadedEventArgs args)
+ {
+ try
+ {
+ var projectGuid = GetProjectId(args);
+ var hashedTargetFrameworks = GetHashedTargetFrameworks(args.ProjectInstance);
+
+ if (args.References == null)
+ {
+ return;
+ }
+
+ var hashedReferences = GetHashedReferences(args);
+ var hashedFileExtensions = GetUniqueHashedFileExtensions(args);
+
+ _eventEmitter.ProjectInformation(projectGuid, hashedTargetFrameworks, hashedReferences, hashedFileExtensions);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError("Unexpected exception got thrown from project load listener: " + ex);
+ }
+ }
+
+ private static IEnumerable GetUniqueHashedFileExtensions(ProjectLoadedEventArgs args)
+ {
+ IEnumerable sourceFileExtensions = args.SourceFiles.Select(file => Path.GetExtension(file)).Distinct();
+ return sourceFileExtensions.Select(_tfmAndFileHashingAlgorithm.HashInput);
+ }
+
+ private static HashedString GetProjectId(ProjectLoadedEventArgs args)
+ {
+ if (args.ProjectIdIsDefinedInSolution)
+ {
+ //If we are getting a raw guid we should not hash it
+ return new HashedString(args.Id.Id.ToString());
+ }
+
+ var projectFilePath = args.ProjectInstance.GetPropertyValue(MSBuildProjectFullPath);
+ var content = File.ReadAllText(projectFilePath);
+ //create a hash from the filename and the content
+ return _referenceHashingAlgorithm.HashInput($"Filename: {Path.GetFileName(projectFilePath)}\n{content}");
+ }
+
+ private static IEnumerable GetHashedReferences(ProjectLoadedEventArgs args)
+ {
+ var referenceNames = args.References.Select(reference => Path.GetFileNameWithoutExtension(reference).ToLower());
+ return referenceNames.Select(_referenceHashingAlgorithm.HashInput);
+ }
+
+ // Internal for testing
+ internal static IEnumerable GetHashedTargetFrameworks(ProjectInstance projectInstance)
+ {
+ var targetFrameworks = projectInstance.GetPropertyValue(TargetFrameworks);
+ if (string.IsNullOrEmpty(targetFrameworks))
+ {
+ targetFrameworks = projectInstance.GetPropertyValue(TargetFramework);
+ }
+ if (string.IsNullOrEmpty(targetFrameworks))
+ {
+ targetFrameworks = projectInstance.GetPropertyValue(TargetFrameworkVersion);
+ }
+
+ if (!string.IsNullOrEmpty(targetFrameworks))
+ {
+ return targetFrameworks.Split(';')
+ .Where(tfm => !string.IsNullOrWhiteSpace(tfm))
+ .Select(tfm => tfm.ToLower())
+ .Select(_tfmAndFileHashingAlgorithm.HashInput);
+ }
+
+ return new List();
+ }
+ }
+}
diff --git a/src/OmniSharp.MSBuild/ProjectManager.cs b/src/OmniSharp.MSBuild/ProjectManager.cs
index 3b37808548..9d74565a2c 100644
--- a/src/OmniSharp.MSBuild/ProjectManager.cs
+++ b/src/OmniSharp.MSBuild/ProjectManager.cs
@@ -29,12 +29,14 @@ internal class ProjectManager : DisposableObject
{
private class ProjectToUpdate
{
+ public ProjectIdInfo ProjectIdInfo;
public string FilePath { get; }
public bool AllowAutoRestore { get; set; }
public ProjectLoadedEventArgs LoadedEventArgs { get; set; }
- public ProjectToUpdate(string filePath, bool allowAutoRestore)
+ public ProjectToUpdate(string filePath, bool allowAutoRestore, ProjectIdInfo projectIdInfo)
{
+ ProjectIdInfo = projectIdInfo ?? throw new ArgumentNullException(nameof(projectIdInfo));
FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath));
AllowAutoRestore = allowAutoRestore;
}
@@ -61,13 +63,13 @@ public ProjectToUpdate(string filePath, bool allowAutoRestore)
private readonly FileSystemNotificationCallback _onDirectoryFileChanged;
- public ProjectManager(ILoggerFactory loggerFactory,
- MSBuildOptions options,
- IEventEmitter eventEmitter,
- IFileSystemWatcher fileSystemWatcher,
- MetadataFileReferenceCache metadataFileReferenceCache,
- PackageDependencyChecker packageDependencyChecker,
- ProjectLoader projectLoader,
+ public ProjectManager(ILoggerFactory loggerFactory,
+ MSBuildOptions options,
+ IEventEmitter eventEmitter,
+ IFileSystemWatcher fileSystemWatcher,
+ MetadataFileReferenceCache metadataFileReferenceCache,
+ PackageDependencyChecker packageDependencyChecker,
+ ProjectLoader projectLoader,
OmniSharpWorkspace workspace,
ImmutableArray eventSinks)
{
@@ -114,7 +116,8 @@ private async Task WaitForProjectModelReadyAsync(string documentPath)
{
if (_projectsRequestedOnDemand.TryAdd(csProjFile, 0 /*unused*/))
{
- QueueProjectUpdate(csProjFile, allowAutoRestore:true);
+ var projectIdInfo = new ProjectIdInfo(ProjectId.CreateNewId(csProjFile), false);
+ QueueProjectUpdate(csProjFile, allowAutoRestore:true, projectIdInfo);
}
}
@@ -123,7 +126,7 @@ private async Task WaitForProjectModelReadyAsync(string documentPath)
projectDir = Path.GetDirectoryName(projectDir);
} while(projectDir != null);
-
+
// Wait for all queued projects to load to ensure that workspace is fully up to date before this method completes.
// If the project for the document was loaded before and there are no other projects to load at the moment, the call below will be no-op.
_logger.LogTrace($"Started waiting for projects queue to be empty when requested '{documentPath}'");
@@ -145,10 +148,10 @@ protected override void DisposeCore(bool disposing)
public IEnumerable GetAllProjects() => _projectFiles.GetItems();
public bool TryGetProject(string projectFilePath, out ProjectFileInfo projectFileInfo) => _projectFiles.TryGetValue(projectFilePath, out projectFileInfo);
- public void QueueProjectUpdate(string projectFilePath, bool allowAutoRestore)
+ public void QueueProjectUpdate(string projectFilePath, bool allowAutoRestore, ProjectIdInfo projectId)
{
_logger.LogInformation($"Queue project update for '{projectFilePath}'");
- _queue.Post(new ProjectToUpdate(projectFilePath, allowAutoRestore));
+ _queue.Post(new ProjectToUpdate(projectFilePath, allowAutoRestore, projectId));
}
public async Task WaitForQueueEmptyAsync()
@@ -227,7 +230,7 @@ private void ProcessQueue(CancellationToken cancellationToken)
}
else
{
- (projectFileInfo, loadedEventArgs) = LoadProject(currentProject.FilePath);
+ (projectFileInfo, loadedEventArgs) = LoadProject(currentProject.FilePath, currentProject.ProjectIdInfo);
if (projectFileInfo == null)
{
_failedToLoadProjectFiles.Add(currentProject.FilePath);
@@ -279,8 +282,8 @@ private void ProcessQueue(CancellationToken cancellationToken)
_fileSystemWatcher.Watch(".cs", _onDirectoryFileChanged);
}
- private (ProjectFileInfo, ProjectLoadedEventArgs) LoadProject(string projectFilePath)
- => LoadOrReloadProject(projectFilePath, () => ProjectFileInfo.Load(projectFilePath, _projectLoader));
+ private (ProjectFileInfo, ProjectLoadedEventArgs) LoadProject(string projectFilePath, ProjectIdInfo idInfo)
+ => LoadOrReloadProject(projectFilePath, () => ProjectFileInfo.Load(projectFilePath, idInfo, _projectLoader));
private (ProjectFileInfo, ProjectLoadedEventArgs) ReloadProject(ProjectFileInfo projectFileInfo)
=> LoadOrReloadProject(projectFileInfo.FilePath, () => projectFileInfo.Reload(_projectLoader));
@@ -361,14 +364,14 @@ private void WatchProjectFiles(ProjectFileInfo projectFileInfo)
// as "updates". We should properly remove projects that are deleted.
_fileSystemWatcher.Watch(projectFileInfo.FilePath, (file, changeType) =>
{
- QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: true);
+ QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: true, projectFileInfo.ProjectIdInfo);
});
if (!string.IsNullOrEmpty(projectFileInfo.ProjectAssetsFile))
{
_fileSystemWatcher.Watch(projectFileInfo.ProjectAssetsFile, (file, changeType) =>
{
- QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false);
+ QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo);
});
var restoreDirectory = Path.GetDirectoryName(projectFileInfo.ProjectAssetsFile);
@@ -379,17 +382,17 @@ private void WatchProjectFiles(ProjectFileInfo projectFileInfo)
_fileSystemWatcher.Watch(nugetCacheFile, (file, changeType) =>
{
- QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false);
+ QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo);
});
_fileSystemWatcher.Watch(nugetPropsFile, (file, changeType) =>
{
- QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false);
+ QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo);
});
_fileSystemWatcher.Watch(nugetTargetsFile, (file, changeType) =>
{
- QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false);
+ QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo);
});
}
}
@@ -418,7 +421,11 @@ private void UpdateProject(string projectFilePath)
private void UpdateSourceFiles(Project project, IList sourceFiles)
{
- var currentDocuments = project.Documents.ToDictionary(d => d.FilePath, d => d.Id);
+ // Remove transient documents from list of current documents, to assure proper new documents are added.
+ // Transient documents will be removed on workspace DocumentAdded event.
+ var currentDocuments = project.Documents
+ .Where(document => !_workspace.BufferManager.IsTransientDocument(document.Id))
+ .ToDictionary(d => d.FilePath, d => d.Id);
// Add source files to the project.
foreach (var sourceFile in sourceFiles)
@@ -522,7 +529,7 @@ private void UpdateProjectReferences(Project project, ImmutableArray pro
referencedProject = ProjectFileInfo.CreateNoBuild(projectReferencePath, _projectLoader);
AddProject(referencedProject);
- QueueProjectUpdate(projectReferencePath, allowAutoRestore: true);
+ QueueProjectUpdate(projectReferencePath, allowAutoRestore: true, referencedProject.ProjectIdInfo);
}
}
@@ -585,6 +592,21 @@ private void UpdateReferences(Project project, ImmutableArray projectRef
if (!referencesToAdd.Contains(reference))
{
+ if (_projectFiles.TryGetValue(project.FilePath, out var projectFileInfo))
+ {
+ if (projectFileInfo.ReferenceAliases != null && projectFileInfo.ReferenceAliases.TryGetValue(referencePath, out var aliases))
+ {
+ if (!string.IsNullOrEmpty(aliases))
+ {
+ reference = reference.WithAliases(aliases.Split(';'));
+ _logger.LogDebug($"setting aliases: {referencePath}, {aliases} ");
+ }
+ }
+ }
+ else
+ {
+ _logger.LogDebug($"failed to get project info:{project.FilePath}");
+ }
_logger.LogDebug($"Adding reference '{referencePath}' to '{project.Name}'.");
_workspace.AddMetadataReference(project.Id, reference);
referencesToAdd.Add(reference);
diff --git a/src/OmniSharp.MSBuild/ProjectSystem.cs b/src/OmniSharp.MSBuild/ProjectSystem.cs
index 0165e45067..a5fede9d27 100644
--- a/src/OmniSharp.MSBuild/ProjectSystem.cs
+++ b/src/OmniSharp.MSBuild/ProjectSystem.cs
@@ -99,7 +99,7 @@ public void Initalize(IConfiguration configuration)
_packageDependencyChecker = new PackageDependencyChecker(_loggerFactory, _eventEmitter, _dotNetCli, _options);
_loader = new ProjectLoader(_options, _environment.TargetDirectory, _propertyOverrides, _loggerFactory, _sdksPathResolver);
- _manager = new ProjectManager(_loggerFactory, _options, _eventEmitter, _fileSystemWatcher, _metadataFileReferenceCache, _packageDependencyChecker,
+ _manager = new ProjectManager(_loggerFactory, _options, _eventEmitter, _fileSystemWatcher, _metadataFileReferenceCache, _packageDependencyChecker,
_loader, _workspace, _eventSinks);
if (_options.LoadProjectsOnDemand)
@@ -108,9 +108,9 @@ public void Initalize(IConfiguration configuration)
return;
}
- var initialProjectPaths = GetInitialProjectPaths();
+ var initialProjectPathsAndIds = GetInitialProjectPathsAndIds();
- foreach (var projectFilePath in initialProjectPaths)
+ foreach (var (projectFilePath, projectIdInfo) in initialProjectPathsAndIds)
{
if (!File.Exists(projectFilePath))
{
@@ -118,17 +118,17 @@ public void Initalize(IConfiguration configuration)
continue;
}
- _manager.QueueProjectUpdate(projectFilePath, allowAutoRestore: true);
+ _manager.QueueProjectUpdate(projectFilePath, allowAutoRestore: true, projectIdInfo);
}
}
- private IEnumerable GetInitialProjectPaths()
+ private IEnumerable<(string, ProjectIdInfo)> GetInitialProjectPathsAndIds()
{
// If a solution was provided, use it.
if (!string.IsNullOrEmpty(_environment.SolutionFilePath))
{
_solutionFileOrRootPath = _environment.SolutionFilePath;
- return GetProjectPathsFromSolution(_environment.SolutionFilePath);
+ return GetProjectPathsAndIdsFromSolution(_environment.SolutionFilePath);
}
// Otherwise, assume that the path provided is a directory and look for a solution there.
@@ -136,22 +136,27 @@ private IEnumerable GetInitialProjectPaths()
if (!string.IsNullOrEmpty(solutionFilePath))
{
_solutionFileOrRootPath = solutionFilePath;
- return GetProjectPathsFromSolution(solutionFilePath);
+ return GetProjectPathsAndIdsFromSolution(solutionFilePath);
}
// Finally, if there isn't a single solution immediately available,
// Just process all of the projects beneath the root path.
_solutionFileOrRootPath = _environment.TargetDirectory;
- return _fileSystemHelper.GetFiles("**/*.csproj");
+ return _fileSystemHelper.GetFiles("**/*.csproj")
+ .Select(filepath =>
+ {
+ var projectIdInfo = new ProjectIdInfo(ProjectId.CreateNewId(debugName: filepath), isDefinedInSolution: false);
+ return (filepath, projectIdInfo);
+ });
}
- private IEnumerable GetProjectPathsFromSolution(string solutionFilePath)
+ private IEnumerable<(string, ProjectIdInfo)> GetProjectPathsAndIdsFromSolution(string solutionFilePath)
{
_logger.LogInformation($"Detecting projects in '{solutionFilePath}'.");
var solutionFile = SolutionFile.ParseFile(solutionFilePath);
var processedProjects = new HashSet(StringComparer.OrdinalIgnoreCase);
- var result = new List();
+ var result = new List<(string, ProjectIdInfo)>();
foreach (var project in solutionFile.Projects)
{
@@ -173,7 +178,8 @@ private IEnumerable GetProjectPathsFromSolution(string solutionFilePath)
if (string.Equals(Path.GetExtension(projectFilePath), ".csproj", StringComparison.OrdinalIgnoreCase))
{
- result.Add(projectFilePath);
+ var projectIdInfo = new ProjectIdInfo(ProjectId.CreateFromSerialized(new Guid(project.ProjectGuid)), true);
+ result.Add((projectFilePath, projectIdInfo));
}
processedProjects.Add(projectFilePath);
diff --git a/src/OmniSharp.MSBuild/VsReferenceHashingAlgorithm.cs b/src/OmniSharp.MSBuild/VsReferenceHashingAlgorithm.cs
new file mode 100644
index 0000000000..a02d2300b8
--- /dev/null
+++ b/src/OmniSharp.MSBuild/VsReferenceHashingAlgorithm.cs
@@ -0,0 +1,121 @@
+using OmniSharp.Models;
+using System.Text;
+
+namespace OmniSharp.MSBuild
+{
+ public class VsReferenceHashingAlgorithm : IHasher
+ {
+ private static readonly ulong[] _hashText = {
+ 0x0000000000000000, 0x0809e8a2969451e9, 0x1013d1452d28a3d2, 0x181a39e7bbbcf23b,
+ 0x2027a28a5a5147a4, 0x282e4a28ccc5164d, 0x303473cf7779e476, 0x383d9b6de1edb59f,
+ 0x404f4514b4a28f48, 0x4846adb62236dea1, 0x505c9451998a2c9a, 0x58557cf30f1e7d73,
+ 0x6068e79eeef3c8ec, 0x68610f3c78679905, 0x707b36dbc3db6b3e, 0x7872de79554f3ad7,
+ 0x809e8a2969451e90, 0x8897628bffd14f79, 0x908d5b6c446dbd42, 0x9884b3ced2f9ecab,
+ 0xa0b928a333145934, 0xa8b0c001a58008dd, 0xb0aaf9e61e3cfae6, 0xb8a3114488a8ab0f,
+ 0xc0d1cf3ddde791d8, 0xc8d8279f4b73c031, 0xd0c21e78f0cf320a, 0xd8cbf6da665b63e3,
+ 0xe0f66db787b6d67c, 0xe8ff851511228795, 0xf0e5bcf2aa9e75ae, 0xf8ec54503c0a2447,
+ 0x24b1909974c84e69, 0x2cb8783be25c1f80, 0x34a241dc59e0edbb, 0x3caba97ecf74bc52,
+ 0x049632132e9909cd, 0x0c9fdab1b80d5824, 0x1485e35603b1aa1f, 0x1c8c0bf49525fbf6,
+ 0x64fed58dc06ac121, 0x6cf73d2f56fe90c8, 0x74ed04c8ed4262f3, 0x7ce4ec6a7bd6331a,
+ 0x44d977079a3b8685, 0x4cd09fa50cafd76c, 0x54caa642b7132557, 0x5cc34ee0218774be,
+ 0xa42f1ab01d8d50f9, 0xac26f2128b190110, 0xb43ccbf530a5f32b, 0xbc352357a631a2c2,
+ 0x8408b83a47dc175d, 0x8c015098d14846b4, 0x941b697f6af4b48f, 0x9c1281ddfc60e566,
+ 0xe4605fa4a92fdfb1, 0xec69b7063fbb8e58, 0xf4738ee184077c63, 0xfc7a664312932d8a,
+ 0xc447fd2ef37e9815, 0xcc4e158c65eac9fc, 0xd4542c6bde563bc7, 0xdc5dc4c948c26a2e,
+ 0x49632132e9909cd2, 0x416ac9907f04cd3b, 0x5970f077c4b83f00, 0x517918d5522c6ee9,
+ 0x694483b8b3c1db76, 0x614d6b1a25558a9f, 0x795752fd9ee978a4, 0x715eba5f087d294d,
+ 0x092c64265d32139a, 0x01258c84cba64273, 0x193fb563701ab048, 0x11365dc1e68ee1a1,
+ 0x290bc6ac0763543e, 0x21022e0e91f705d7, 0x391817e92a4bf7ec, 0x3111ff4bbcdfa605,
+ 0xc9fdab1b80d58242, 0xc1f443b91641d3ab, 0xd9ee7a5eadfd2190, 0xd1e792fc3b697079,
+ 0xe9da0991da84c5e6, 0xe1d3e1334c10940f, 0xf9c9d8d4f7ac6634, 0xf1c03076613837dd,
+ 0x89b2ee0f34770d0a, 0x81bb06ada2e35ce3, 0x99a13f4a195faed8, 0x91a8d7e88fcbff31,
+ 0xa9954c856e264aae, 0xa19ca427f8b21b47, 0xb9869dc0430ee97c, 0xb18f7562d59ab895,
+ 0x6dd2b1ab9d58d2bb, 0x65db59090bcc8352, 0x7dc160eeb0707169, 0x75c8884c26e42080,
+ 0x4df51321c709951f, 0x45fcfb83519dc4f6, 0x5de6c264ea2136cd, 0x55ef2ac67cb56724,
+ 0x2d9df4bf29fa5df3, 0x25941c1dbf6e0c1a, 0x3d8e25fa04d2fe21, 0x3587cd589246afc8,
+ 0x0dba563573ab1a57, 0x05b3be97e53f4bbe, 0x1da987705e83b985, 0x15a06fd2c817e86c,
+ 0xed4c3b82f41dcc2b, 0xe545d32062899dc2, 0xfd5feac7d9356ff9, 0xf55602654fa13e10,
+ 0xcd6b9908ae4c8b8f, 0xc56271aa38d8da66, 0xdd78484d8364285d, 0xd571a0ef15f079b4,
+ 0xad037e9640bf4363, 0xa50a9634d62b128a, 0xbd10afd36d97e0b1, 0xb5194771fb03b158,
+ 0x8d24dc1c1aee04c7, 0x852d34be8c7a552e, 0x9d370d5937c6a715, 0x953ee5fba152f6fc,
+ 0x92c64265d32139a4, 0x9acfaac745b5684d, 0x82d59320fe099a76, 0x8adc7b82689dcb9f,
+ 0xb2e1e0ef89707e00, 0xbae8084d1fe42fe9, 0xa2f231aaa458ddd2, 0xaafbd90832cc8c3b,
+ 0xd28907716783b6ec, 0xda80efd3f117e705, 0xc29ad6344aab153e, 0xca933e96dc3f44d7,
+ 0xf2aea5fb3dd2f148, 0xfaa74d59ab46a0a1, 0xe2bd74be10fa529a, 0xeab49c1c866e0373,
+ 0x1258c84cba642734, 0x1a5120ee2cf076dd, 0x024b1909974c84e6, 0x0a42f1ab01d8d50f,
+ 0x327f6ac6e0356090, 0x3a76826476a13179, 0x226cbb83cd1dc342, 0x2a6553215b8992ab,
+ 0x52178d580ec6a87c, 0x5a1e65fa9852f995, 0x42045c1d23ee0bae, 0x4a0db4bfb57a5a47,
+ 0x72302fd25497efd8, 0x7a39c770c203be31, 0x6223fe9779bf4c0a, 0x6a2a1635ef2b1de3,
+ 0xb677d2fca7e977cd, 0xbe7e3a5e317d2624, 0xa66403b98ac1d41f, 0xae6deb1b1c5585f6,
+ 0x96507076fdb83069, 0x9e5998d46b2c6180, 0x8643a133d09093bb, 0x8e4a49914604c252,
+ 0xf63897e8134bf885, 0xfe317f4a85dfa96c, 0xe62b46ad3e635b57, 0xee22ae0fa8f70abe,
+ 0xd61f3562491abf21, 0xde16ddc0df8eeec8, 0xc60ce42764321cf3, 0xce050c85f2a64d1a,
+ 0x36e958d5ceac695d, 0x3ee0b077583838b4, 0x26fa8990e384ca8f, 0x2ef3613275109b66,
+ 0x16cefa5f94fd2ef9, 0x1ec712fd02697f10, 0x06dd2b1ab9d58d2b, 0x0ed4c3b82f41dcc2,
+ 0x76a61dc17a0ee615, 0x7eaff563ec9ab7fc, 0x66b5cc84572645c7, 0x6ebc2426c1b2142e,
+ 0x5681bf4b205fa1b1, 0x5e8857e9b6cbf058, 0x46926e0e0d770263, 0x4e9b86ac9be3538a,
+ 0xdba563573ab1a576, 0xd3ac8bf5ac25f49f, 0xcbb6b212179906a4, 0xc3bf5ab0810d574d,
+ 0xfb82c1dd60e0e2d2, 0xf38b297ff674b33b, 0xeb9110984dc84100, 0xe398f83adb5c10e9,
+ 0x9bea26438e132a3e, 0x93e3cee118877bd7, 0x8bf9f706a33b89ec, 0x83f01fa435afd805,
+ 0xbbcd84c9d4426d9a, 0xb3c46c6b42d63c73, 0xabde558cf96ace48, 0xa3d7bd2e6ffe9fa1,
+ 0x5b3be97e53f4bbe6, 0x533201dcc560ea0f, 0x4b28383b7edc1834, 0x4321d099e84849dd,
+ 0x7b1c4bf409a5fc42, 0x7315a3569f31adab, 0x6b0f9ab1248d5f90, 0x63067213b2190e79,
+ 0x1b74ac6ae75634ae, 0x137d44c871c26547, 0x0b677d2fca7e977c, 0x036e958d5ceac695,
+ 0x3b530ee0bd07730a, 0x335ae6422b9322e3, 0x2b40dfa5902fd0d8, 0x2349370706bb8131,
+ 0xff14f3ce4e79eb1f, 0xf71d1b6cd8edbaf6, 0xef07228b635148cd, 0xe70eca29f5c51924,
+ 0xdf3351441428acbb, 0xd73ab9e682bcfd52, 0xcf20800139000f69, 0xc72968a3af945e80,
+ 0xbf5bb6dafadb6457, 0xb7525e786c4f35be, 0xaf48679fd7f3c785, 0xa7418f3d4167966c,
+ 0x9f7c1450a08a23f3, 0x9775fcf2361e721a, 0x8f6fc5158da28021, 0x87662db71b36d1c8,
+ 0x7f8a79e7273cf58f, 0x77839145b1a8a466, 0x6f99a8a20a14565d, 0x679040009c8007b4,
+ 0x5faddb6d7d6db22b, 0x57a433cfebf9e3c2, 0x4fbe0a28504511f9, 0x47b7e28ac6d14010,
+ 0x3fc53cf3939e7ac7, 0x37ccd451050a2b2e, 0x2fd6edb6beb6d915, 0x27df0514282288fc,
+ 0x1fe29e79c9cf3d63, 0x17eb76db5f5b6c8a, 0x0ff14f3ce4e79eb1, 0x07f8a79e7273cf58,
+ };
+
+ ///
+ /// The format in which the input stream should be read.abstract Ulong bitmask
+ ///
+ private static readonly ulong _mask = 0xffffffffffffffffUL;
+
+
+ ///
+ /// Helper method to encode an input string in Unicode format before feeding through masking into hash function
+ ///
+ /// The string to be encoded
+ /// An array of byte in unicode format (wchars)
+ private static byte[] EncodeBytes(string cleartext)
+ {
+ return Encoding.Unicode.GetBytes(cleartext);
+ }
+
+ ///
+ /// Calculates the hashed value
+ ///
+ /// Array of byte that repersents the value that needs hashing
+ /// The format in which the input stream should be read: 0xffffffffffffffffUL
+ /// A numerical value that is the hash
+ private static ulong ComputeHash(byte[] inputstream, ulong crc)
+ {
+ for (int j = 0; j < inputstream.Length; j++)
+ {
+ crc = _hashText[(byte)(crc ^ inputstream[j])] ^ (crc >> 8);
+ }
+
+ return crc;
+
+ }
+
+ ///
+ /// Calls the hashing function on the input
+ ///
+ /// The value that should be hashed
+ /// A string representation of the hash value
+ public HashedString HashInput(string cleartext)
+ {
+ ulong hashedBytes = ComputeHash(EncodeBytes(cleartext), _mask);
+
+ return new HashedString(hashedBytes.ToString("x"));
+
+ }
+ }
+}
diff --git a/src/OmniSharp.MSBuild/VsTfmAndFileExtHashingAlgorithm.cs b/src/OmniSharp.MSBuild/VsTfmAndFileExtHashingAlgorithm.cs
new file mode 100644
index 0000000000..e7b0efcde0
--- /dev/null
+++ b/src/OmniSharp.MSBuild/VsTfmAndFileExtHashingAlgorithm.cs
@@ -0,0 +1,57 @@
+using OmniSharp.Models;
+
+namespace OmniSharp.MSBuild
+{
+ public class VsTfmAndFileExtHashingAlgorithm : IHasher
+ {
+ static readonly long[] cr3tab = /* CRC polynomial 0xedb88320 */
+ {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
+ 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
+ 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
+ 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
+ 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
+ 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
+ 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
+ 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
+ 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
+ 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
+ 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
+ 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
+ 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
+ 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
+ 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
+ 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
+ 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
+ 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
+ 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
+ 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
+ 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
+ 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
+ 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
+ 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
+ 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
+ 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
+ };
+
+
+ public HashedString HashInput(string cleartext)
+ {
+ long lHash = 0;
+
+ for (int i = 0; i < cleartext.Length; i++)
+ {
+ lHash = (cr3tab[((int)lHash ^ cleartext[i]) & 0xff] ^ ((lHash >> 8) & 0x00FFFFFFL));
+ }
+
+ int result = (int)lHash; // need to cast it to a DWORD
+ return new HashedString(result.ToString());
+ }
+ }
+}
diff --git a/src/OmniSharp.Roslyn.CSharp/OmniSharp.Roslyn.CSharp.csproj b/src/OmniSharp.Roslyn.CSharp/OmniSharp.Roslyn.CSharp.csproj
index bc165ff264..1f05661ac5 100644
--- a/src/OmniSharp.Roslyn.CSharp/OmniSharp.Roslyn.CSharp.csproj
+++ b/src/OmniSharp.Roslyn.CSharp/OmniSharp.Roslyn.CSharp.csproj
@@ -8,9 +8,11 @@
+
+
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs b/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs
index 16df110506..89fc1a4bd5 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs
@@ -20,6 +20,15 @@ public class TypeLookupService : IRequestHandler Handle(TypeLookupRequest request)
{
response.Type = symbol.Kind == SymbolKind.NamedType ?
symbol.ToDisplayString(DefaultFormat) :
- symbol.ToMinimalDisplayString(semanticModel, position);
+ symbol.ToMinimalDisplayString(semanticModel, position, MinimalFormat);
if (request.IncludeDocumentation)
{
diff --git a/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticService.cs b/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticService.cs
index 03e733f669..f199b90af8 100644
--- a/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Workers/Diagnostics/CSharpDiagnosticService.cs
@@ -1,7 +1,14 @@
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
+using System.Reactive;
+using System.Reactive.Concurrency;
+using System.Reactive.Linq;
+using System.Reactive.Subjects;
+using System.Reactive.Threading;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
@@ -18,8 +25,7 @@ public class CSharpDiagnosticService
private readonly OmniSharpWorkspace _workspace;
private readonly object _lock = new object();
private readonly DiagnosticEventForwarder _forwarder;
- private bool _queueRunning = false;
- private readonly ConcurrentQueue _openDocuments = new ConcurrentQueue();
+ private readonly IObserver _openDocuments;
[ImportingConstructor]
public CSharpDiagnosticService(OmniSharpWorkspace workspace, DiagnosticEventForwarder forwarder, ILoggerFactory loggerFactory)
@@ -28,113 +34,92 @@ public CSharpDiagnosticService(OmniSharpWorkspace workspace, DiagnosticEventForw
_forwarder = forwarder;
_logger = loggerFactory.CreateLogger();
+ var openDocumentsSubject = new Subject();
+ _openDocuments = openDocumentsSubject;
+
_workspace.WorkspaceChanged += OnWorkspaceChanged;
+ _workspace.DocumentOpened += OnDocumentOpened;
+ _workspace.DocumentClosed += OnDocumentOpened;
+
+ openDocumentsSubject
+ .GroupByUntil(x => true, group => Observable.Amb(
+ group.Throttle(TimeSpan.FromMilliseconds(200)),
+ group.Distinct().Skip(99))
+ )
+ .Select(x => x.ToArray())
+ .Merge()
+ .SubscribeOn(TaskPoolScheduler.Default)
+ .Select(ProcessQueue)
+ .Merge()
+ .Subscribe();
}
- private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs changeEvent)
+ private void OnDocumentOpened(object sender, DocumentEventArgs args)
{
- if (changeEvent.Kind == WorkspaceChangeKind.DocumentChanged)
+ if (!_forwarder.IsEnabled)
{
- var newDocument = changeEvent.NewSolution.GetDocument(changeEvent.DocumentId);
-
- this.EmitDiagnostics(newDocument.FilePath);
- foreach (var document in _workspace.GetOpenDocumentIds().Select(x => _workspace.CurrentSolution.GetDocument(x)))
- {
- this.EmitDiagnostics(document.FilePath);
- }
+ return;
}
- }
- public void QueueDiagnostics(params string[] documents)
- {
- this.EmitDiagnostics(documents);
+ EmitDiagnostics(args.Document.FilePath);
+ EmitDiagnostics(_workspace.GetOpenDocumentIds().Select(x => _workspace.CurrentSolution.GetDocument(x).FilePath).ToArray());
}
- private void EmitDiagnostics(params string[] documents)
+ private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs changeEvent)
{
- if (_forwarder.IsEnabled)
+ if (!_forwarder.IsEnabled)
{
- foreach (var document in documents)
- {
- if (!_openDocuments.Contains(document))
- {
- _openDocuments.Enqueue(document);
- }
- }
+ return;
+ }
- if (!_queueRunning && !_openDocuments.IsEmpty)
- {
- this.ProcessQueue();
- }
+ if (changeEvent.Kind == WorkspaceChangeKind.DocumentAdded || changeEvent.Kind == WorkspaceChangeKind.DocumentChanged || changeEvent.Kind == WorkspaceChangeKind.DocumentReloaded)
+ {
+ var newDocument = changeEvent.NewSolution.GetDocument(changeEvent.DocumentId);
+
+ EmitDiagnostics(newDocument.FilePath);
+ EmitDiagnostics(_workspace.GetOpenDocumentIds().Select(x => _workspace.CurrentSolution.GetDocument(x).FilePath).ToArray());
+ }
+ else if (changeEvent.Kind == WorkspaceChangeKind.ProjectAdded || changeEvent.Kind == WorkspaceChangeKind.ProjectReloaded)
+ {
+ EmitDiagnostics(changeEvent.NewSolution.GetProject(changeEvent.ProjectId).Documents.Select(x => x.FilePath).ToArray());
}
}
- private void ProcessQueue()
+ public void QueueDiagnostics(params string[] documents)
{
- lock (_lock)
+ if (!_forwarder.IsEnabled)
{
- _queueRunning = true;
+ return;
}
- Task.Factory.StartNew(async () =>
- {
- await Task.Delay(100);
- await Dequeue();
-
- if (_openDocuments.IsEmpty)
- {
- lock (_lock)
- {
- _queueRunning = false;
- }
- }
- else
- {
- this.ProcessQueue();
- }
- });
+ this.EmitDiagnostics(documents);
}
- private async Task Dequeue()
+ private void EmitDiagnostics(params string[] documents)
{
- var tasks = new List>();
- for (var i = 0; i < 50; i++)
+ if (!_forwarder.IsEnabled)
{
- if (_openDocuments.IsEmpty)
- {
- break;
- }
-
- if (_openDocuments.TryDequeue(out var filePath))
- {
- tasks.Add(this.ProcessNextItem(filePath));
- }
+ return;
}
- if (!tasks.Any()) return;
+ foreach (var document in documents)
+ {
+ _openDocuments.OnNext(document);
+ }
+ }
- var diagnosticResults = await Task.WhenAll(tasks.ToArray());
- if (diagnosticResults.Any())
+ private IObservable ProcessQueue(IEnumerable filePaths)
+ {
+ return Observable.FromAsync(async () =>
{
+ var results = await Task.WhenAll(filePaths.Distinct().Select(ProcessNextItem));
var message = new DiagnosticMessage()
{
- Results = diagnosticResults
+ Results = results
};
- this._forwarder.Forward(message);
- }
-
- if (_openDocuments.IsEmpty)
- {
- lock (_lock)
- {
- _queueRunning = false;
- }
- }
- else
- {
- this.ProcessQueue();
- }
+ _forwarder.Forward(message);
+ });
}
private async Task ProcessNextItem(string filePath)
diff --git a/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs b/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
index d6dc9b9734..d64b17a659 100644
--- a/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Workers/Refactoring/FixUsingsWorker.cs
@@ -51,80 +51,60 @@ private static CodeFixProvider FindCodeFixProviderByTypeFullName(IEnumerable FixUsingsAsync(Document document)
{
- document = await AddMissingUsingsAsync(document);
+ var missingUsings = await AddMissingUsingsAsync(document);
+
+ document = missingUsings.Document;
document = await RemoveUnnecessaryUsingsAsync(document);
document = await TryAddLinqQuerySyntaxAsync(document);
- var ambiguous = await GetAmbiguousUsingsAsync(document);
-
- var response = new FixUsingsWorkerResponse()
+ return new FixUsingsWorkerResponse()
{
- AmbiguousResults = ambiguous,
+ AmbiguousResults = missingUsings.AmbiguousUsings,
Document = document
};
-
- response.AmbiguousResults = ambiguous;
- response.Document = document;
-
- return response;
}
- private async Task> GetAmbiguousUsingsAsync(Document document)
+ private async Task TrackAmbiguousQuickFix(IList results, IList ambiguousNodes, SimpleNameSyntax name, ImmutableArray operations, Document document)
{
- var ambiguousNodes = new List();
- var results = new List();
+ ambiguousNodes.Add(name);
+ var unresolvedText = name.Identifier.ValueText;
+ var unresolvedLocation = name.GetLocation().GetLineSpan().StartLinePosition;
+ var ambiguousNamespaces = await GetAmbiguousNamespacesAsync(operations, document);
- var semanticModel = await document.GetSemanticModelAsync();
- var root = await semanticModel.SyntaxTree.GetRootAsync();
-
- var simpleNames = root
- .DescendantNodes()
- .OfType()
- .Where(x => semanticModel.GetSymbolInfo(x).Symbol == null)
- .ToArray();
-
- foreach (var name in simpleNames)
- {
- if (ambiguousNodes.Contains(name))
+ results.Add(new QuickFix
{
- continue;
- }
-
- var diagnostics = await GetDiagnosticsAtSpanAsync(document, name.Identifier.Span, "CS0246", "CS1061", "CS0103");
- if (diagnostics.Any())
- {
- var span = diagnostics.First().Location.SourceSpan;
- if (diagnostics.Any(d => d.Location.SourceSpan != span))
- {
- continue;
- }
-
- var operations = await GetCodeFixOperationsAsync(_addImportProvider, document, span, diagnostics);
+ Line = unresolvedLocation.Line,
+ Column = unresolvedLocation.Character,
+ FileName = document.FilePath,
+ Text = $"`{unresolvedText}` is ambiguous. Namespaces:{ambiguousNamespaces}"
+ });
+ }
- if (operations.Length > 1)
- {
- // More than one operation - ambiguous
- ambiguousNodes.Add(name);
- var unresolvedText = name.Identifier.ValueText;
- var unresolvedLocation = name.GetLocation().GetLineSpan().StartLinePosition;
+ private async Task GetAmbiguousNamespacesAsync(ImmutableArray operations, Document document)
+ {
+ var namespaces = new List();
+ foreach (var operation in operations.Where(x => x is ApplyChangesOperation))
+ {
+ var newSolution = ((ApplyChangesOperation)operation).ChangedSolution;
+ var newDocument = newSolution.GetDocument(document.Id);
- results.Add(
- new QuickFix
- {
- Line = unresolvedLocation.Line,
- Column = unresolvedLocation.Character,
- FileName = document.FilePath,
- Text = "`" + unresolvedText + "`" + " is ambiguous"
- });
- }
- }
+ var changes = await newDocument.GetTextChangesAsync(document);
+ foreach (var change in changes)
+ namespaces.Add(change.NewText.Trim());
}
- return results;
+ var ambiguousNamespaces = string.Empty;
+ foreach (var uniqueNamespace in namespaces.Distinct())
+ ambiguousNamespaces += $" {uniqueNamespace}";
+
+ return ambiguousNamespaces;
}
- private async Task AddMissingUsingsAsync(Document document)
+ private async Task AddMissingUsingsAsync(Document document)
{
+ var ambiguousNodes = new List();
+ var quickFixes = new List();
+
while (true)
{
var semanticModel = await document.GetSemanticModelAsync();
@@ -140,6 +120,11 @@ private async Task AddMissingUsingsAsync(Document document)
foreach (var name in unboundNames)
{
+ if (ambiguousNodes.Contains(name))
+ {
+ continue;
+ }
+
var diagnostics = await GetDiagnosticsAtSpanAsync(document, name.Identifier.Span, "CS0246", "CS1061", "CS0103");
if (diagnostics.Any())
{
@@ -152,7 +137,9 @@ private async Task AddMissingUsingsAsync(Document document)
var operations = await GetCodeFixOperationsAsync(_addImportProvider, document, span, diagnostics);
- if (operations.Length == 1 && operations[0] is ApplyChangesOperation)
+ if (operations.Length > 1)
+ await TrackAmbiguousQuickFix(quickFixes, ambiguousNodes, name, operations, document);
+ else if (operations.Length == 1 && operations[0] is ApplyChangesOperation)
{
// Only one operation - apply it and loop back around
var newSolution = ((ApplyChangesOperation)operations[0]).ChangedSolution;
@@ -172,7 +159,7 @@ private async Task AddMissingUsingsAsync(Document document)
}
}
- return document;
+ return new MissingUsingsResult { Document = document, AmbiguousUsings = quickFixes };
}
private async Task RemoveUnnecessaryUsingsAsync(Document document)
@@ -326,5 +313,11 @@ private static bool IsLinqQuerySyntax(SyntaxNode node)
return false;
}
}
+
+ private class MissingUsingsResult
+ {
+ public Document Document { get; set; }
+ public IEnumerable AmbiguousUsings { get; set; }
+ }
}
}
diff --git a/src/OmniSharp.Roslyn/BufferManager.cs b/src/OmniSharp.Roslyn/BufferManager.cs
index 07a3b5e91e..c40b5deaa1 100644
--- a/src/OmniSharp.Roslyn/BufferManager.cs
+++ b/src/OmniSharp.Roslyn/BufferManager.cs
@@ -29,6 +29,14 @@ public BufferManager(OmniSharpWorkspace workspace, IFileSystemWatcher fileSystem
_onFileChanged = OnFileChanged;
}
+ public bool IsTransientDocument(DocumentId documentId)
+ {
+ lock(_lock)
+ {
+ return _transientDocumentIds.Contains(documentId);
+ }
+ }
+
public async Task UpdateBufferAsync(Request request)
{
var buffer = request.Buffer;
diff --git a/src/OmniSharp.Roslyn/OmniSharp.Roslyn.csproj b/src/OmniSharp.Roslyn/OmniSharp.Roslyn.csproj
index a111489d6e..03b646a616 100644
--- a/src/OmniSharp.Roslyn/OmniSharp.Roslyn.csproj
+++ b/src/OmniSharp.Roslyn/OmniSharp.Roslyn.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/OmniSharp.Roslyn/OmniSharpWorkspace.cs b/src/OmniSharp.Roslyn/OmniSharpWorkspace.cs
index b6d38d6c16..756039c9eb 100644
--- a/src/OmniSharp.Roslyn/OmniSharpWorkspace.cs
+++ b/src/OmniSharp.Roslyn/OmniSharpWorkspace.cs
@@ -335,7 +335,7 @@ private void SaveDocumentText(DocumentId id, string fullPath, SourceText newText
try
{
var dir = Path.GetDirectoryName(fullPath);
- if (!Directory.Exists(dir))
+ if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
diff --git a/src/OmniSharp.Shared/AssemblyInfo.cs b/src/OmniSharp.Shared/AssemblyInfo.cs
new file mode 100644
index 0000000000..6abd59bc91
--- /dev/null
+++ b/src/OmniSharp.Shared/AssemblyInfo.cs
@@ -0,0 +1,9 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("OmniSharp")]
+[assembly: InternalsVisibleTo("OmniSharp.Host")]
+[assembly: InternalsVisibleTo("OmniSharp.MSBuild")]
+[assembly: InternalsVisibleTo("OmniSharp.Roslyn")]
+[assembly: InternalsVisibleTo("OmniSharp.Roslyn.CSharp")]
+[assembly: InternalsVisibleTo("OmniSharp.DotNetTest.Tests")]
+[assembly: InternalsVisibleTo("OmniSharp.Tests")]
diff --git a/src/OmniSharp.Abstractions/FileSystem/FileSystemHelper.cs b/src/OmniSharp.Shared/FileSystem/FileSystemHelper.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/FileSystem/FileSystemHelper.cs
rename to src/OmniSharp.Shared/FileSystem/FileSystemHelper.cs
diff --git a/src/OmniSharp.Abstractions/Logging/BaseLogger.cs b/src/OmniSharp.Shared/Logging/BaseLogger.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Logging/BaseLogger.cs
rename to src/OmniSharp.Shared/Logging/BaseLogger.cs
diff --git a/src/OmniSharp.Shared/OmniSharp.Shared.csproj b/src/OmniSharp.Shared/OmniSharp.Shared.csproj
new file mode 100644
index 0000000000..0756f4b88c
--- /dev/null
+++ b/src/OmniSharp.Shared/OmniSharp.Shared.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net461
+ AnyCPU
+ OmniSharp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/OmniSharp.Abstractions/Options/FileOptions.cs b/src/OmniSharp.Shared/Options/FileOptions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Options/FileOptions.cs
rename to src/OmniSharp.Shared/Options/FileOptions.cs
diff --git a/src/OmniSharp.Abstractions/Options/FormattingOptions.cs b/src/OmniSharp.Shared/Options/FormattingOptions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Options/FormattingOptions.cs
rename to src/OmniSharp.Shared/Options/FormattingOptions.cs
diff --git a/src/OmniSharp.Abstractions/Options/OmniSharpOptions.cs b/src/OmniSharp.Shared/Options/OmniSharpOptions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Options/OmniSharpOptions.cs
rename to src/OmniSharp.Shared/Options/OmniSharpOptions.cs
diff --git a/src/OmniSharp.Abstractions/Options/RoslynExtensionsOptions.cs b/src/OmniSharp.Shared/Options/RoslynExtensionsOptions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Options/RoslynExtensionsOptions.cs
rename to src/OmniSharp.Shared/Options/RoslynExtensionsOptions.cs
diff --git a/src/OmniSharp.Abstractions/ProjectSystemNames.cs b/src/OmniSharp.Shared/ProjectSystemNames.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/ProjectSystemNames.cs
rename to src/OmniSharp.Shared/ProjectSystemNames.cs
diff --git a/src/OmniSharp.Abstractions/TransportType.cs b/src/OmniSharp.Shared/TransportType.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/TransportType.cs
rename to src/OmniSharp.Shared/TransportType.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/CachedStringBuilder.cs b/src/OmniSharp.Shared/Utilities/CachedStringBuilder.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/CachedStringBuilder.cs
rename to src/OmniSharp.Shared/Utilities/CachedStringBuilder.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/DictionaryExtensions.cs b/src/OmniSharp.Shared/Utilities/DictionaryExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/DictionaryExtensions.cs
rename to src/OmniSharp.Shared/Utilities/DictionaryExtensions.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/DisposableObject.cs b/src/OmniSharp.Shared/Utilities/DisposableObject.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/DisposableObject.cs
rename to src/OmniSharp.Shared/Utilities/DisposableObject.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/ImmutableArrayExtensions.cs b/src/OmniSharp.Shared/Utilities/ImmutableArrayExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/ImmutableArrayExtensions.cs
rename to src/OmniSharp.Shared/Utilities/ImmutableArrayExtensions.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.DisposableChangeCallback.cs b/src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.DisposableChangeCallback.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.DisposableChangeCallback.cs
rename to src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.DisposableChangeCallback.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.PhysicalFileProviderWrapper.cs b/src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.PhysicalFileProviderWrapper.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.PhysicalFileProviderWrapper.cs
rename to src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.PhysicalFileProviderWrapper.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.PollingFileChangeToken.cs b/src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.PollingFileChangeToken.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.PollingFileChangeToken.cs
rename to src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.PollingFileChangeToken.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.cs b/src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/PhysicalFileProviderExtensions.cs
rename to src/OmniSharp.Shared/Utilities/PhysicalFileProviderExtensions.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/Platform.cs b/src/OmniSharp.Shared/Utilities/Platform.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/Platform.cs
rename to src/OmniSharp.Shared/Utilities/Platform.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/PlatformHelper.cs b/src/OmniSharp.Shared/Utilities/PlatformHelper.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/PlatformHelper.cs
rename to src/OmniSharp.Shared/Utilities/PlatformHelper.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/ProcessExitStatus.cs b/src/OmniSharp.Shared/Utilities/ProcessExitStatus.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/ProcessExitStatus.cs
rename to src/OmniSharp.Shared/Utilities/ProcessExitStatus.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/ProcessExtensions.cs b/src/OmniSharp.Shared/Utilities/ProcessExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/ProcessExtensions.cs
rename to src/OmniSharp.Shared/Utilities/ProcessExtensions.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/ProcessHelper.cs b/src/OmniSharp.Shared/Utilities/ProcessHelper.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/ProcessHelper.cs
rename to src/OmniSharp.Shared/Utilities/ProcessHelper.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/ReflectionExtensions.cs b/src/OmniSharp.Shared/Utilities/ReflectionExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/ReflectionExtensions.cs
rename to src/OmniSharp.Shared/Utilities/ReflectionExtensions.cs
diff --git a/src/OmniSharp.Abstractions/Utilities/TaskExtensions.cs b/src/OmniSharp.Shared/Utilities/TaskExtensions.cs
similarity index 100%
rename from src/OmniSharp.Abstractions/Utilities/TaskExtensions.cs
rename to src/OmniSharp.Shared/Utilities/TaskExtensions.cs
diff --git a/src/OmniSharp.Stdio.Driver/app.config b/src/OmniSharp.Stdio.Driver/app.config
index 4e0d1de440..a725124756 100644
--- a/src/OmniSharp.Stdio.Driver/app.config
+++ b/src/OmniSharp.Stdio.Driver/app.config
@@ -7,15 +7,15 @@
-
+
-
+
-
+
diff --git a/src/OmniSharp.Stdio/Eventing/StdioEventEmitter.cs b/src/OmniSharp.Stdio/Eventing/StdioEventEmitter.cs
index 9564bda337..c9c485a0f0 100644
--- a/src/OmniSharp.Stdio/Eventing/StdioEventEmitter.cs
+++ b/src/OmniSharp.Stdio/Eventing/StdioEventEmitter.cs
@@ -1,6 +1,6 @@
using OmniSharp.Eventing;
-using OmniSharp.Stdio.Protocol;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Protocol;
+using OmniSharp.Services;
namespace OmniSharp.Stdio.Eventing
{
diff --git a/src/OmniSharp.Stdio/Host.cs b/src/OmniSharp.Stdio/Host.cs
index 6962584cd6..1a034eebb4 100644
--- a/src/OmniSharp.Stdio/Host.cs
+++ b/src/OmniSharp.Stdio/Host.cs
@@ -14,8 +14,7 @@
using OmniSharp.Models.UpdateBuffer;
using OmniSharp.Plugins;
using OmniSharp.Services;
-using OmniSharp.Stdio.Protocol;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Protocol;
using OmniSharp.Utilities;
namespace OmniSharp.Stdio
diff --git a/src/OmniSharp.Stdio/Logging/StdioLogger.cs b/src/OmniSharp.Stdio/Logging/StdioLogger.cs
index eec6667e65..2cefc42743 100644
--- a/src/OmniSharp.Stdio/Logging/StdioLogger.cs
+++ b/src/OmniSharp.Stdio/Logging/StdioLogger.cs
@@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging;
using OmniSharp.Logging;
-using OmniSharp.Stdio.Protocol;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Protocol;
+using OmniSharp.Services;
namespace OmniSharp.Stdio.Logging
{
diff --git a/src/OmniSharp.Stdio/Logging/StdioLoggerExtensions.cs b/src/OmniSharp.Stdio/Logging/StdioLoggerExtensions.cs
index 3226491425..1a1bb80537 100644
--- a/src/OmniSharp.Stdio/Logging/StdioLoggerExtensions.cs
+++ b/src/OmniSharp.Stdio/Logging/StdioLoggerExtensions.cs
@@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Services;
namespace OmniSharp.Stdio.Logging
{
diff --git a/src/OmniSharp.Stdio/Logging/StdioLoggerProvider.cs b/src/OmniSharp.Stdio/Logging/StdioLoggerProvider.cs
index 04565256ad..b87b55780f 100644
--- a/src/OmniSharp.Stdio/Logging/StdioLoggerProvider.cs
+++ b/src/OmniSharp.Stdio/Logging/StdioLoggerProvider.cs
@@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Services;
namespace OmniSharp.Stdio.Logging
{
diff --git a/test-assets/test-projects/CSharp8AndNullableContext/CSharp8AndNullableContext.csproj b/test-assets/test-projects/CSharp8AndNullableContext/CSharp8AndNullableContext.csproj
new file mode 100644
index 0000000000..f8c35733c7
--- /dev/null
+++ b/test-assets/test-projects/CSharp8AndNullableContext/CSharp8AndNullableContext.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ netcoreapp2.1
+ 8.0
+ enable
+
+
+
\ No newline at end of file
diff --git a/test-assets/test-projects/CSharp8AndNullableContext/Program.cs b/test-assets/test-projects/CSharp8AndNullableContext/Program.cs
new file mode 100644
index 0000000000..cd8f0e5063
--- /dev/null
+++ b/test-assets/test-projects/CSharp8AndNullableContext/Program.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace ConsoleApplication
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ string? foo = null;
+ string bar = null;
+ Console.WriteLine(foo + bar);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test-assets/test-projects/ExternAlias/ExternAlias.App/ExternAlias.App.csproj b/test-assets/test-projects/ExternAlias/ExternAlias.App/ExternAlias.App.csproj
new file mode 100644
index 0000000000..f2bf085d0a
--- /dev/null
+++ b/test-assets/test-projects/ExternAlias/ExternAlias.App/ExternAlias.App.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ netcoreapp2.1
+
+
+
+
+ false
+
+
+ $(ProjectDir)../ExternAlias.Lib/bin/$(Configuration)/netstandard2.0/ExternAlias.Lib.dll
+ abc
+
+
+
+
diff --git a/test-assets/test-projects/ExternAlias/ExternAlias.App/Program.cs b/test-assets/test-projects/ExternAlias/ExternAlias.App/Program.cs
new file mode 100644
index 0000000000..3364a344bd
--- /dev/null
+++ b/test-assets/test-projects/ExternAlias/ExternAlias.App/Program.cs
@@ -0,0 +1,14 @@
+extern alias abc;
+using System;
+
+namespace ExternAlias.App
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ new abc::ExternAlias.Lib.Class1();
+ Console.WriteLine("Hello World!");
+ }
+ }
+}
diff --git a/test-assets/test-projects/ExternAlias/ExternAlias.Lib/Class1.cs b/test-assets/test-projects/ExternAlias/ExternAlias.Lib/Class1.cs
new file mode 100644
index 0000000000..7b90a3ec53
--- /dev/null
+++ b/test-assets/test-projects/ExternAlias/ExternAlias.Lib/Class1.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace ExternAlias.Lib
+{
+ public class Class1
+ {
+ }
+}
diff --git a/test-assets/test-projects/ExternAlias/ExternAlias.Lib/ExternAlias.Lib.csproj b/test-assets/test-projects/ExternAlias/ExternAlias.Lib/ExternAlias.Lib.csproj
new file mode 100644
index 0000000000..9f5c4f4abb
--- /dev/null
+++ b/test-assets/test-projects/ExternAlias/ExternAlias.Lib/ExternAlias.Lib.csproj
@@ -0,0 +1,7 @@
+
+
+
+ netstandard2.0
+
+
+
diff --git a/test-assets/test-projects/ExternAlias/ExternAlias.sln b/test-assets/test-projects/ExternAlias/ExternAlias.sln
new file mode 100644
index 0000000000..91117aba9a
--- /dev/null
+++ b/test-assets/test-projects/ExternAlias/ExternAlias.sln
@@ -0,0 +1,48 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternAlias.App", "ExternAlias.App\ExternAlias.App.csproj", "{447E6D15-63B0-47F3-9E44-D6F0D0087C46}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternAlias.Lib", "ExternAlias.Lib\ExternAlias.Lib.csproj", "{ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|x64.Build.0 = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Debug|x86.Build.0 = Debug|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|Any CPU.Build.0 = Release|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|x64.ActiveCfg = Release|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|x64.Build.0 = Release|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|x86.ActiveCfg = Release|Any CPU
+ {447E6D15-63B0-47F3-9E44-D6F0D0087C46}.Release|x86.Build.0 = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|x64.Build.0 = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Debug|x86.Build.0 = Debug|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x64.ActiveCfg = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x64.Build.0 = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x86.ActiveCfg = Release|Any CPU
+ {ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/test-assets/test-projects/HelloWorld/HelloWorld.csproj b/test-assets/test-projects/HelloWorld/HelloWorld.csproj
index c0318399b6..c9b3d73a3f 100644
--- a/test-assets/test-projects/HelloWorld/HelloWorld.csproj
+++ b/test-assets/test-projects/HelloWorld/HelloWorld.csproj
@@ -2,20 +2,8 @@
Exe
- netcoreapp1.0
- false
+ netcoreapp2.1
7.1
-
-
-
-
-
-
-
- 1.0.1
-
-
-
-
\ No newline at end of file
+
diff --git a/test-assets/test-projects/HelloWorld/Program.cs b/test-assets/test-projects/HelloWorld/Program.cs
index 031164913c..8168c80511 100644
--- a/test-assets/test-projects/HelloWorld/Program.cs
+++ b/test-assets/test-projects/HelloWorld/Program.cs
@@ -1,12 +1,12 @@
-using System;
+using System;
-namespace ConsoleApplication
+namespace HelloWorld
{
- public class Program
+ class Program
{
- public static void Main(string[] args)
+ static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/OmniSharp.MSBuild.Tests/MSBuildSelectionTests.cs b/tests/OmniSharp.MSBuild.Tests/MSBuildSelectionTests.cs
new file mode 100644
index 0000000000..d527ee4a62
--- /dev/null
+++ b/tests/OmniSharp.MSBuild.Tests/MSBuildSelectionTests.cs
@@ -0,0 +1,131 @@
+using System;
+using OmniSharp.MSBuild.Discovery;
+using TestUtility;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OmniSharp.MSBuild.Tests
+{
+ public class MSBuildSelectionTests : AbstractTestFixture
+ {
+ public MSBuildSelectionTests(ITestOutputHelper output)
+ : base(output)
+ {
+ }
+
+ [Fact]
+ public void RegisterDefaultInstanceFindsTheBestInstanceAvailable()
+ {
+ var msBuildInstances = new[]
+ {
+ GetInvalidMsBuildInstance(),
+ // Valid
+ new MSBuildInstance(
+ "Test Instance",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("15.1.2.3"),
+ DiscoveryType.VisualStudioSetup
+ ).AddDotNetCoreToFakeInstance(),
+ GetStandAloneMSBuildInstance()
+ };
+
+ var msbuildLocator = new MSFakeLocator(msBuildInstances);
+ var logger = LoggerFactory.CreateLogger(nameof(RegisterDefaultInstanceFindsTheBestInstanceAvailable));
+
+ // test
+ msbuildLocator.RegisterDefaultInstance(logger);
+
+ Assert.NotNull(msbuildLocator.RegisteredInstance);
+ Assert.Same(msBuildInstances[1], msbuildLocator.RegisteredInstance);
+
+ // clean up
+ msbuildLocator.DeleteFakeInstancesFolders();
+ }
+
+ [Fact]
+ public void RegisterDefaultInstanceFindsTheBestInstanceAvailableEvenWithOtherValidInstances()
+ {
+ var msBuildInstances = new[]
+ {
+ new MSBuildInstance(
+ "Valid Test Instance",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("15.3.2.1"),
+ DiscoveryType.VisualStudioSetup
+ ),
+ GetInvalidMsBuildInstance(),
+
+ // Valid + Dotnet Core
+ new MSBuildInstance(
+ "Another Valid Test Instance",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("15.1.2.3"),
+ DiscoveryType.VisualStudioSetup
+ ).AddDotNetCoreToFakeInstance(),
+ GetStandAloneMSBuildInstance()
+ };
+
+ var msbuildLocator = new MSFakeLocator(msBuildInstances);
+
+ var logger = LoggerFactory.CreateLogger(
+ nameof(RegisterDefaultInstanceFindsTheBestInstanceAvailableEvenWithOtherValidInstances)
+ );
+
+ // test
+ msbuildLocator.RegisterDefaultInstance(logger);
+
+ Assert.NotNull(msbuildLocator.RegisteredInstance);
+ Assert.Same(msBuildInstances[2], msbuildLocator.RegisteredInstance);
+
+ // clean up
+ msbuildLocator.DeleteFakeInstancesFolders();
+ }
+
+ [Fact]
+ public void RegisterDefaultInstanceStillPrefersTheFirstInstance()
+ {
+ var msBuildInstances = new[]
+ {
+ new MSBuildInstance(
+ "Test Instance",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("15.1.2.3"),
+ DiscoveryType.VisualStudioSetup
+ ),
+ GetStandAloneMSBuildInstance()
+ };
+
+ var msbuildLocator = new MSFakeLocator(msBuildInstances);
+ var logger = LoggerFactory.CreateLogger(nameof(RegisterDefaultInstanceStillPrefersTheFirstInstance));
+
+ // test
+ msbuildLocator.RegisterDefaultInstance(logger);
+
+ Assert.NotNull(msbuildLocator.RegisteredInstance);
+ Assert.Same(msBuildInstances[0], msbuildLocator.RegisteredInstance);
+
+ // clean up
+ msbuildLocator.DeleteFakeInstancesFolders();
+ }
+
+ private static MSBuildInstance GetStandAloneMSBuildInstance()
+ {
+ return new MSBuildInstance(
+ "Stand Alone :(",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("99.0.0.0"),
+ DiscoveryType.StandAlone
+ );
+ }
+
+ private static MSBuildInstance GetInvalidMsBuildInstance()
+ {
+ return new MSBuildInstance(
+ "Invalid Instance",
+ TestIO.GetRandomTempFolderPath(),
+ Version.Parse("15.0.4.2"),
+ DiscoveryType.VisualStudioSetup
+ );
+ }
+ }
+}
diff --git a/tests/OmniSharp.MSBuild.Tests/ProjectFileInfoTests.cs b/tests/OmniSharp.MSBuild.Tests/ProjectFileInfoTests.cs
index 6203cb2e75..c943baec87 100644
--- a/tests/OmniSharp.MSBuild.Tests/ProjectFileInfoTests.cs
+++ b/tests/OmniSharp.MSBuild.Tests/ProjectFileInfoTests.cs
@@ -1,5 +1,6 @@
using System.IO;
using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using OmniSharp.MSBuild.Discovery;
using OmniSharp.MSBuild.ProjectFile;
@@ -32,7 +33,8 @@ private ProjectFileInfo CreateProjectFileInfo(OmniSharpTestHost host, ITestProje
loggerFactory: LoggerFactory,
sdksPathResolver: sdksPathResolver);
- var (projectFileInfo, _, _) = ProjectFileInfo.Load(projectFilePath, loader);
+ var projectIdInfo = new ProjectIdInfo(ProjectId.CreateNewId(), false);
+ var (projectFileInfo, _, _) = ProjectFileInfo.Load(projectFilePath, projectIdInfo, loader);
return projectFileInfo;
}
@@ -50,9 +52,9 @@ public async Task HelloWorld_has_correct_property_values()
Assert.NotNull(projectFileInfo);
Assert.Equal(projectFilePath, projectFileInfo.FilePath);
var targetFramework = Assert.Single(projectFileInfo.TargetFrameworks);
- Assert.Equal("netcoreapp1.0", targetFramework);
- Assert.Equal("bin/Debug/netcoreapp1.0/", projectFileInfo.OutputPath.EnsureForwardSlashes());
- Assert.Equal("obj/Debug/netcoreapp1.0/", projectFileInfo.IntermediateOutputPath.EnsureForwardSlashes());
+ Assert.Equal("netcoreapp2.1", targetFramework);
+ Assert.Equal("bin/Debug/netcoreapp2.1/", projectFileInfo.OutputPath.EnsureForwardSlashes());
+ Assert.Equal("obj/Debug/netcoreapp2.1/", projectFileInfo.IntermediateOutputPath.EnsureForwardSlashes());
Assert.Equal(3, projectFileInfo.SourceFiles.Length); // Program.cs, AssemblyInfo.cs, AssemblyAttributes.cs
Assert.Equal(LanguageVersion.CSharp7_1, projectFileInfo.LanguageVersion);
Assert.Equal("Debug", projectFileInfo.Configuration);
@@ -104,5 +106,46 @@ public async Task NetStandardAndNetCoreApp_has_correct_property_values()
Assert.Equal("AnyCPU", projectFileInfo.Platform);
}
}
+
+ [Fact]
+ public async Task CSharp8AndNullableContext_has_correct_property_values()
+ {
+ using (var host = CreateOmniSharpHost())
+ using (var testProject = await _testAssets.GetTestProjectAsync("CSharp8AndNullableContext"))
+ {
+ var projectFilePath = Path.Combine(testProject.Directory, "CSharp8AndNullableContext.csproj");
+
+ var projectFileInfo = CreateProjectFileInfo(host, testProject, projectFilePath);
+
+ Assert.NotNull(projectFileInfo);
+ Assert.Equal(projectFilePath, projectFileInfo.FilePath);
+ var targetFramework = Assert.Single(projectFileInfo.TargetFrameworks);
+ Assert.Equal("netcoreapp2.1", targetFramework);
+ Assert.Equal(LanguageVersion.CSharp8, projectFileInfo.LanguageVersion);
+ Assert.Equal(NullableContextOptions.Enable, projectFileInfo.NullableContextOptions);
+ Assert.Equal("Debug", projectFileInfo.Configuration);
+ Assert.Equal("AnyCPU", projectFileInfo.Platform);
+ }
+ }
+
+ [Fact]
+ public async Task ExternAlias()
+ {
+ using (var host = CreateOmniSharpHost())
+ using (var testProject = await _testAssets.GetTestProjectAsync("ExternAlias"))
+ {
+ var projectFilePath = Path.Combine(testProject.Directory, "ExternAlias.App", "ExternAlias.App.csproj");
+ var projectFileInfo = CreateProjectFileInfo(host, testProject, projectFilePath);
+ Assert.Single(projectFileInfo.ReferenceAliases);
+ foreach(var kv in projectFileInfo.ReferenceAliases)
+ {
+ this.TestOutput.WriteLine($"{kv.Key} = {kv.Value}");
+ }
+ // reference path should be same as evaluated HintPath("$(ProjectDir)../ExternAlias.Lib/bin/Debug/netstandard2.0/ExternAlias.Lib.dll")
+ var libpath = string.Format($"{Path.Combine(testProject.Directory, "ExternAlias.App")}{Path.DirectorySeparatorChar}../ExternAlias.Lib/bin/Debug/netstandard2.0/ExternAlias.Lib.dll");
+ Assert.True(projectFileInfo.ReferenceAliases.ContainsKey(libpath));
+ Assert.Equal("abc", projectFileInfo.ReferenceAliases[libpath]);
+ }
+ }
}
}
diff --git a/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs b/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs
new file mode 100644
index 0000000000..c35449252b
--- /dev/null
+++ b/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs
@@ -0,0 +1,249 @@
+using Microsoft.Build.Construction;
+using Microsoft.Build.Execution;
+using Microsoft.CodeAnalysis;
+using Microsoft.Extensions.Logging;
+using OmniSharp.Mef;
+using OmniSharp.Models;
+using OmniSharp.Models.Events;
+using OmniSharp.MSBuild.Notification;
+using OmniSharp.Services;
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Composition.Hosting.Core;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using TestUtility;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OmniSharp.MSBuild.Tests
+{
+ public partial class ProjectLoadListenerTests : AbstractMSBuildTestFixture
+ {
+ private VsTfmAndFileExtHashingAlgorithm _tfmAndFileHashingAlgorithm;
+ private VsReferenceHashingAlgorithm _referenceHashingAlgorithm;
+
+ public ProjectLoadListenerTests(ITestOutputHelper output) : base(output)
+ {
+ _tfmAndFileHashingAlgorithm = new VsTfmAndFileExtHashingAlgorithm();
+ _referenceHashingAlgorithm = new VsReferenceHashingAlgorithm();
+ }
+
+ [Fact]
+ public void GetTargetFramework_ReturnsTargetFramework()
+ {
+ // Arrange
+
+ const string targetFramework = "net461";
+ var expectedTFM = GetHashedTargetFramework(targetFramework);
+ var projectInstance = new ProjectInstance(ProjectRootElement.Create());
+ projectInstance.SetProperty(ProjectLoadListener.TargetFramework, targetFramework);
+
+ // Act
+ var tfm = ProjectLoadListener.GetHashedTargetFrameworks(projectInstance);
+
+ // Assert
+ Assert.Equal(expectedTFM, tfm.First().Value);
+ }
+
+ [Fact]
+ public void GetTargetFramework_NoTFM_ReturnsTargetFrameworkVersion()
+ {
+ // Arrange
+ const string targetFramework = "v4.6.1";
+ var expectedTFM = GetHashedTargetFramework(targetFramework);
+ var projectInstance = new ProjectInstance(ProjectRootElement.Create());
+ projectInstance.SetProperty(ProjectLoadListener.TargetFrameworkVersion, targetFramework);
+
+ // Act
+ var tfm = ProjectLoadListener.GetHashedTargetFrameworks(projectInstance);
+
+ // Assert
+ Assert.Equal(expectedTFM, tfm.First().Value);
+ }
+
+ [Fact]
+ public void GetTargetFramework_PrioritizesTargetFrameworkOverVersion()
+ {
+ // Arrange
+ const string targetFramework = "v4.6.1";
+ var expectedTFM = GetHashedTargetFramework(targetFramework);
+ var projectInstance = new ProjectInstance(ProjectRootElement.Create());
+ projectInstance.SetProperty(ProjectLoadListener.TargetFramework, targetFramework);
+ projectInstance.SetProperty(ProjectLoadListener.TargetFrameworkVersion, "Unexpected");
+
+ // Act
+ var tfm = ProjectLoadListener.GetHashedTargetFrameworks(projectInstance);
+
+ // Assert
+ Assert.Equal(expectedTFM, tfm.First().Value);
+ }
+
+ [Fact]
+ public void GetTargetFramework_NoTFM_ReturnsEmpty()
+ {
+ // Arrange
+ var projectInstance = new ProjectInstance(ProjectRootElement.Create());
+
+ // Act
+ var tfm = ProjectLoadListener.GetHashedTargetFrameworks(projectInstance);
+
+ // Assert
+ Assert.Empty(tfm);
+ }
+
+ [Fact]
+ public async Task The_target_framework_is_emitted()
+ {
+ // Arrange
+ var expectedTFM = GetHashedTargetFramework("netcoreapp2.1");
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ Assert.Single(messages);
+ Assert.Equal(messages[0].TargetFrameworks.First(), expectedTFM);
+ }
+ }
+
+ [Fact]
+ public async Task If_there_is_a_solution_file_the_project_guid_present_in_it_is_emitted()
+ {
+ // Arrange
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectAndSolution"))
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ var expectedGuid = "A4C2694D-AEB4-4CB1-8951-5290424EF883".ToLower();
+ Assert.Single(messages);
+ Assert.Equal(messages[0].ProjectGuid, expectedGuid);
+ }
+ }
+
+ [Fact]
+ public async Task If_there_is_no_solution_file_the_hash_of_project_file_content_and_name_is_emitted()
+ {
+ // Arrange
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ var projectFileContent = File.ReadAllText(Directory.GetFiles(testProject.Directory, "*.csproj").Single());
+ var expectedGuid = GetHashedReference($"Filename: HelloWorld.csproj\n{projectFileContent}");
+ Assert.Single(messages);
+ Assert.Equal(messages[0].ProjectGuid, expectedGuid);
+ }
+ }
+
+ [Fact]
+ public async Task Given_a_restored_project_the_references_are_emitted()
+ {
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
+ {
+ var dotnetCliService = new DotNetCliService(LoggerFactory, emitter);
+ await dotnetCliService.RestoreAsync(testProject.Directory);
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ Assert.Single(messages);
+ Assert.NotEmpty(messages[0].References.Where(reference => reference == GetHashedReference("system.core")));
+ }
+ }
+ }
+
+
+ [Fact]
+ public async Task If_there_are_multiple_target_frameworks_they_are_emitted()
+ {
+ // Arrange
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectWithMultiTFMLib/Lib"))
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ Assert.Single(messages);
+ var tfm = messages[0].TargetFrameworks.ToArray();
+ Assert.Equal(2, tfm.Count());
+ Assert.Equal(tfm[0], GetHashedTargetFramework("netstandard1.3"));
+ Assert.Equal(tfm[1], GetHashedTargetFramework("netstandard2.0"));
+ }
+ }
+
+ [Fact]
+ public async Task The_hashed_references_of_the_source_files_are_emitted()
+ {
+ // Arrange
+ var messages = new List();
+ var emitter = new ProjectLoadTestEventEmitter(messages);
+
+ var listener = new ProjectLoadListener(LoggerFactory, emitter);
+ var exports = new ExportDescriptorProvider[]
+ {
+ MefValueProvider.From(listener)
+ };
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
+ using (var host = CreateMSBuildTestHost(testProject.Directory, exports))
+ {
+ Assert.Single(messages);
+ Assert.Single(messages[0].FileExtensions);
+ Assert.Equal(messages[0].FileExtensions.First(), GetHashedFileExtension(".cs"));
+ }
+ }
+
+ private string GetHashedTargetFramework(string targetFramework)
+ {
+ return _tfmAndFileHashingAlgorithm.HashInput(targetFramework).Value;
+ }
+
+ private string GetHashedFileExtension(string fileExtension)
+ {
+ return _tfmAndFileHashingAlgorithm.HashInput(fileExtension).Value;
+ }
+ private string GetHashedReference(string reference)
+ {
+ return _referenceHashingAlgorithm.HashInput(reference).Value;
+ }
+ }
+}
diff --git a/tests/OmniSharp.MSBuild.Tests/ProjectLoadTestEventEmitter.cs b/tests/OmniSharp.MSBuild.Tests/ProjectLoadTestEventEmitter.cs
new file mode 100644
index 0000000000..833ce81c07
--- /dev/null
+++ b/tests/OmniSharp.MSBuild.Tests/ProjectLoadTestEventEmitter.cs
@@ -0,0 +1,27 @@
+using OmniSharp.Eventing;
+using OmniSharp.Models.Events;
+using System.Collections.Generic;
+
+namespace OmniSharp.MSBuild.Tests
+{
+ public partial class ProjectLoadListenerTests
+ {
+ public class ProjectLoadTestEventEmitter : IEventEmitter
+ {
+ private readonly IList _messages;
+
+ public ProjectLoadTestEventEmitter(IList messages)
+ {
+ _messages = messages;
+ }
+
+ public void Emit(string kind, object args)
+ {
+ if(args is ProjectConfigurationMessage)
+ {
+ _messages.Add((ProjectConfigurationMessage)args);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/DiagnosticsV2Facts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/DiagnosticsV2Facts.cs
index 08d0d76d5c..5a0701b59e 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/DiagnosticsV2Facts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/DiagnosticsV2Facts.cs
@@ -17,7 +17,7 @@ public DiagnosticsV2Facts(ITestOutputHelper output, SharedOmniSharpHostFixture s
{
}
- [Theory]
+ [Theory(Skip = "Test needs to be updated for service changes")]
[InlineData("a.cs")]
[InlineData("a.csx")]
public async Task CodeCheckSpecifiedFileOnly(string filename)
@@ -45,7 +45,7 @@ public async Task CodeCheckSpecifiedFileOnly(string filename)
Assert.Equal(filename, result.FileName);
}
- [Theory]
+ [Theory(Skip = "Test needs to be updated for service changes")]
[InlineData("a.cs", "b.cs")]
[InlineData("a.csx", "b.csx")]
public async Task CheckAllFiles(string filename1, string filename2)
@@ -77,7 +77,7 @@ public async Task CheckAllFiles(string filename1, string filename2)
Assert.Equal(filename2, b.FileName);
}
- [Theory]
+ [Theory(Skip = "Test needs to be updated for service changes")]
[InlineData("a.cs", "b.cs")]
[InlineData("a.csx", "b.csx")]
public async Task EnablesWhenEndPointIsHit(string filename1, string filename2)
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/FixUsingsFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/FixUsingsFacts.cs
index 88f9471832..43f58c1812 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/FixUsingsFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/FixUsingsFacts.cs
@@ -250,7 +250,7 @@ public method1()
Line = point.Line,
Column = point.Offset,
FileName = TestFileName,
- Text = "`classX` is ambiguous"
+ Text = "`classX` is ambiguous. Namespaces: using nsA; using nsB;",
}
};
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/HighlightFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/HighlightFacts.cs
index 026f7d042a..232d506e87 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/HighlightFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/HighlightFacts.cs
@@ -56,7 +56,7 @@ class C1 { int n = true; }
AssertSyntax(highlights, testFile.Content.Code, 0,
Keyword("namespace"),
- Identifier("N1"),
+ NamespaceName("N1"),
Punctuation("{"),
Keyword("class"),
ClassName("C1"),
@@ -236,6 +236,7 @@ private static void AssertSyntax(HighlightSpan[] highlights, string code, int st
private static (string kind, string text) ClassName(string text) => ("class name", text);
private static (string kind, string text) Field(string text) => ("field name", text);
private static (string kind, string text) Identifier(string text) => ("identifier", text);
+ private static (string kind, string text) NamespaceName(string text) => ("namespace name", text);
private static (string kind, string text) Keyword(string text) => ("keyword", text);
private static (string kind, string text) Number(string text) => ("number", text);
private static (string kind, string text) Operator(string text) => ("operator", text);
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
index 6a251adfae..f1985ebd9a 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
@@ -282,7 +282,7 @@ public MyClass2()
";
var completions = await FindCompletionsAsync(filename, source);
- ContainsCompletions(completions.Select(c => c.CompletionText).Take(1), "text:");
+ ContainsCompletions(completions.Select(c => c.CompletionText).Take(1), "text");
}
[Theory]
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs
index 47ce7a5757..6da9517a0c 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs
@@ -147,6 +147,8 @@ public Foo() {
public IDictionary> SomeDict { get; }
public void Compute(int index = 2) { }
+
+ private const int foo = 1;
}
}
@@ -154,6 +156,13 @@ namespace Bar2 {
class Foo2 {
}
}
+
+ namespace Bar3 {
+ enum Foo3 {
+ Val1 = 1,
+ Val2
+ }
+ }
");
[Fact]
@@ -234,6 +243,20 @@ public async Task DisplayFormatFor_FieldSymbol()
Assert.Equal("Foo2 Foo._someField", response.Type);
}
+ [Fact]
+ public async Task DisplayFormatFor_FieldSymbol_WithConstantValue()
+ {
+ var response = await GetTypeLookUpResponse(line: 19, column: 41);
+ Assert.Equal("int Foo.foo = 1", response.Type);
+ }
+
+ [Fact]
+ public async Task DisplayFormatFor_EnumValue()
+ {
+ var response = await GetTypeLookUpResponse(line: 31, column: 23);
+ Assert.Equal("Foo3.Val2 = 2", response.Type);
+ }
+
[Fact]
public async Task DisplayFormatFor_PropertySymbol()
{
diff --git a/tests/OmniSharp.Stdio.Tests/StdioServerFacts.cs b/tests/OmniSharp.Stdio.Tests/StdioServerFacts.cs
index 00c8d55425..bfe751e74d 100644
--- a/tests/OmniSharp.Stdio.Tests/StdioServerFacts.cs
+++ b/tests/OmniSharp.Stdio.Tests/StdioServerFacts.cs
@@ -5,9 +5,8 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using OmniSharp.Eventing;
+using OmniSharp.Protocol;
using OmniSharp.Services;
-using OmniSharp.Stdio.Protocol;
-using OmniSharp.Stdio.Services;
using Xunit;
namespace OmniSharp.Stdio.Tests
diff --git a/tests/OmniSharp.Stdio.Tests/TestTextWriter.cs b/tests/OmniSharp.Stdio.Tests/TestTextWriter.cs
index 20388e50b1..124726f385 100644
--- a/tests/OmniSharp.Stdio.Tests/TestTextWriter.cs
+++ b/tests/OmniSharp.Stdio.Tests/TestTextWriter.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Services;
namespace OmniSharp.Stdio.Tests
{
@@ -44,4 +44,4 @@ public Task WriteLineAsync(object value)
return Task.Factory.StartNew(() => WriteLine(value));
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/OmniSharp.Tests/UpdateBufferFilterFacts.cs b/tests/OmniSharp.Tests/UpdateBufferFilterFacts.cs
index c3afc6f632..66d8d6fa4d 100644
--- a/tests/OmniSharp.Tests/UpdateBufferFilterFacts.cs
+++ b/tests/OmniSharp.Tests/UpdateBufferFilterFacts.cs
@@ -6,6 +6,8 @@
using TestUtility;
using Xunit;
using Xunit.Abstractions;
+using System;
+using System.Threading;
namespace OmniSharp.Tests
{
@@ -70,7 +72,7 @@ public async Task UpdateBuffer_AddsNewDocumentsIfNeeded()
}
}
- [Fact(Skip = "Fails on line 95 because there are 3 documents, not 2, named 'transient.cs'")]
+ [Fact]
public async Task UpdateBuffer_TransientDocumentsDisappearWhenProjectAddsThem()
{
var testFile = new TestFile("test.cs", "class C {}");
@@ -88,11 +90,29 @@ public async Task UpdateBuffer_TransientDocumentsDisappearWhenProjectAddsThem()
loader: TextLoader.From(TextAndVersion.Create(SourceText.From("enum E{}"), VersionStamp.Create())),
filePath: "transient.cs");
+ // apply changes - this raises workspaceChanged event asynchronously.
var newSolution = host.Workspace.CurrentSolution.AddDocument(document);
host.Workspace.TryApplyChanges(newSolution);
- docIds = host.Workspace.CurrentSolution.GetDocumentIdsWithFilePath("transient.cs");
- Assert.Equal(2, docIds.Length);
+ // wait for workspaceChange event to be raised.
+ var cts = new CancellationTokenSource();
+ cts.CancelAfter(TimeSpan.FromSeconds(10));
+ while (!cts.IsCancellationRequested)
+ {
+ await Task.Yield();
+ docIds = host.Workspace.CurrentSolution.GetDocumentIdsWithFilePath("transient.cs");
+ if (docIds.Count() <= 1) break;
+ }
+
+ // assert that only one document with "transient.cs" filePath remains
+ Assert.Single(docIds);
+
+ // assert that the remaining document is part of project1
+ project1 = host.Workspace.CurrentSolution.GetProject(project1.Id);
+ Assert.Contains(docIds[0], project1.DocumentIds);
+
+ // assert that the remaining document is not transient.
+ Assert.False(host.Workspace.BufferManager.IsTransientDocument(docIds[0]));
await host.Workspace.BufferManager.UpdateBufferAsync(new Request() { FileName = "transient.cs", Buffer = "enum E {}" });
var sourceText = await host.Workspace.CurrentSolution.GetDocument(docIds.First()).GetTextAsync();
diff --git a/tests/TestUtility/MSFakeLocator.cs b/tests/TestUtility/MSFakeLocator.cs
new file mode 100644
index 0000000000..41ca907b41
--- /dev/null
+++ b/tests/TestUtility/MSFakeLocator.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.IO;
+using OmniSharp.MSBuild.Discovery;
+
+namespace TestUtility
+{
+ public class MSFakeLocator : IMSBuildLocator
+ {
+ private readonly ImmutableArray _instances;
+
+ public MSBuildInstance RegisteredInstance { get; private set; }
+
+ public MSFakeLocator(IEnumerable instances)
+ {
+ _instances = instances.ToImmutableArray();
+ }
+
+ public void RegisterInstance(MSBuildInstance instance)
+ => RegisteredInstance = instance;
+
+ public ImmutableArray GetInstances()
+ => _instances;
+
+ public void DeleteFakeInstancesFolders()
+ {
+ foreach (var instance in _instances)
+ {
+ if (Directory.Exists(instance.MSBuildPath))
+ Directory.Delete(instance.MSBuildPath, true);
+ }
+ }
+ }
+}
diff --git a/tests/TestUtility/TestFolder.cs b/tests/TestUtility/TestFolder.cs
new file mode 100644
index 0000000000..7517c96e4f
--- /dev/null
+++ b/tests/TestUtility/TestFolder.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace TestUtility
+{
+ public static class TestIO
+ {
+ public static string GetRandomTempFolderPath()
+ {
+ var path = Path.Combine(
+ Path.GetTempPath(),
+ Path.GetRandomFileName()
+ );
+
+ Directory.CreateDirectory(path);
+
+ return path;
+ }
+
+ public static void TouchFakeFile(string path)
+ {
+ File.WriteAllText(path, "just testing :)");
+ }
+ }
+}
diff --git a/tests/TestUtility/TestHelpers.cs b/tests/TestUtility/TestHelpers.cs
index a2f4c34a75..1820c81fa0 100644
--- a/tests/TestUtility/TestHelpers.cs
+++ b/tests/TestUtility/TestHelpers.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
@@ -7,6 +8,7 @@
using Microsoft.Extensions.Logging;
using OmniSharp;
using OmniSharp.FileWatching;
+using OmniSharp.MSBuild.Discovery;
using OmniSharp.Script;
using OmniSharp.Services;
@@ -24,7 +26,7 @@ public static OmniSharpWorkspace CreateCsxWorkspace(TestFile testFile)
public static void AddCsxProjectToWorkspace(OmniSharpWorkspace workspace, TestFile testFile)
{
var references = GetReferences();
- var scriptHelper = new ScriptProjectProvider(new ScriptOptions(), new OmniSharpEnvironment(), new LoggerFactory(), true);
+ var scriptHelper = new ScriptProjectProvider(new ScriptOptions(), new OmniSharpEnvironment(), new LoggerFactory(), true);
var project = scriptHelper.CreateProject(testFile.FileName, references.Union(new[] { MetadataReference.CreateFromFile(typeof(CommandLineScriptGlobals).GetTypeInfo().Assembly.Location) }), testFile.FileName, typeof(CommandLineScriptGlobals), Enumerable.Empty());
workspace.AddProject(project);
@@ -91,5 +93,22 @@ private static IEnumerable GetReferences()
return references;
}
+
+ public static MSBuildInstance AddDotNetCoreToFakeInstance(this MSBuildInstance instance)
+ {
+ const string dotnetSdkResolver = "Microsoft.DotNet.MSBuildSdkResolver";
+
+ var directory = Path.Combine(
+ instance.MSBuildPath,
+ "SdkResolvers",
+ dotnetSdkResolver
+ );
+
+ Directory.CreateDirectory(directory);
+
+ TestIO.TouchFakeFile(Path.Combine(directory, dotnetSdkResolver + ".dll"));
+
+ return instance;
+ }
}
}
diff --git a/tests/TestUtility/TestServiceProvider.cs b/tests/TestUtility/TestServiceProvider.cs
index e13242ba37..15efceda42 100644
--- a/tests/TestUtility/TestServiceProvider.cs
+++ b/tests/TestUtility/TestServiceProvider.cs
@@ -11,7 +11,6 @@
using OmniSharp.MSBuild.Discovery;
using OmniSharp.Options;
using OmniSharp.Services;
-using OmniSharp.Stdio.Services;
using OmniSharp.Utilities;
using TestUtility.Logging;
using Xunit.Abstractions;
diff --git a/tests/TestUtility/TestSharedTextWriter.cs b/tests/TestUtility/TestSharedTextWriter.cs
index 3433e79897..c61c05f11d 100644
--- a/tests/TestUtility/TestSharedTextWriter.cs
+++ b/tests/TestUtility/TestSharedTextWriter.cs
@@ -1,5 +1,5 @@
using System.Threading.Tasks;
-using OmniSharp.Stdio.Services;
+using OmniSharp.Services;
using Xunit.Abstractions;
namespace TestUtility
diff --git a/tests/TestUtility/TestUtility.csproj b/tests/TestUtility/TestUtility.csproj
index 14de90b483..5828ebd8df 100644
--- a/tests/TestUtility/TestUtility.csproj
+++ b/tests/TestUtility/TestUtility.csproj
@@ -13,6 +13,7 @@
+
diff --git a/tests/app.config b/tests/app.config
index 34fb8c206a..45e6a8ef7e 100644
--- a/tests/app.config
+++ b/tests/app.config
@@ -7,15 +7,15 @@
-
+
-
+
-
+