diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a1555a6e7..c7f035d54f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,31 @@
# Changelog
All changes to the project will be documented in this file.
+## [1.37.2] - Not Yet Released
+* Add support for new quick info endpoint when working with Cake (PR: [#1945](https://github.com/OmniSharp/omnisharp-roslyn/pull/1945))
+* Add support for new completion endpoints when working with Cake ([#1939](https://github.com/OmniSharp/omnisharp-roslyn/issues/1939), PR: [#1944](https://github.com/OmniSharp/omnisharp-roslyn/pull/1944))
+
+## [1.37.1] - 2020-09-01
+* Ensure that all quickinfo sections have linebreaks between them, and don't add unecessary duplicate linebreaks (PR: [#1900](https://github.com/OmniSharp/omnisharp-roslyn/pull/1900))
+* Support completion of unimported types (PR: [#1896](https://github.com/OmniSharp/omnisharp-roslyn/pull/1896))
+* Exclude Misc project from InternalsVisibleTo completion (PR: [#1902](https://github.com/OmniSharp/omnisharp-roslyn/pull/1902))
+* Ensure unimported things are sorted after imported things (PR: [#1903](https://github.com/OmniSharp/omnisharp-roslyn/pull/1903))
+* Updated lsp library to fix issue with signature help, etc ([#1887](https://github.com/OmniSharp/omnisharp-roslyn/issues/1887), PR: [#1890](https://github.com/OmniSharp/omnisharp-roslyn/pull/1890))
+* Correctly handle multiple reference aliases (PR: [#1905](https://github.com/OmniSharp/omnisharp-roslyn/pull/1905))
+* Better handle completion when the display text is not in the final result (PR: [#1908](https://github.com/OmniSharp/omnisharp-roslyn/pull/1908))
+* Correctly mark hover markup content as markdown ([#1906](https://github.com/OmniSharp/omnisharp-roslyn/issues/1906), PR: [#1909](https://github.com/OmniSharp/omnisharp-roslyn/pull/1909))
+* Upgrade lsp ([#1898](https://github.com/OmniSharp/omnisharp-roslyn/issues/1898), PR: [#1911](https://github.com/OmniSharp/omnisharp-roslyn/pull/1911))
+* Updated to ILSpy 6.1.0.5902 (PR: [#1913](https://github.com/OmniSharp/omnisharp-roslyn/pull/1913))
+* Updated to NET 5.0 preview8 (PR: [#1916](https://github.com/OmniSharp/omnisharp-roslyn/pull/1916))
+* Add HTTP Driver back to build.json (PR: [#1918](https://github.com/OmniSharp/omnisharp-roslyn/pull/1918))
+* Use ExecutionPolicy Bypass when running powershell.exe (PR: [#1917](https://github.com/OmniSharp/omnisharp-roslyn/pull/1917))
+* Update the package that Arch Linux users need to install (PR: [#1921](https://github.com/OmniSharp/omnisharp-roslyn/pull/1921))
+* Updated the docs to mention .NET 4.7.2 targeting pack (PR: [#1922](https://github.com/OmniSharp/omnisharp-roslyn/pull/1922))
+* Support for configurations remapping in solution files ([#1828](https://github.com/OmniSharp/omnisharp-roslyn/issues/1828), PR: [#1835](https://github.com/OmniSharp/omnisharp-roslyn/pull/1835))
+* Only run dotnet --info once for the working directory (PR: [#1925](https://github.com/OmniSharp/omnisharp-roslyn/pull/1925))
+* Update build tool versions for NET 5 RC1 (PR: [#1926](https://github.com/OmniSharp/omnisharp-roslyn/pull/1926))
+* Update Roslyn to 3.8.0-3.20451.2 (PR: [#1927](https://github.com/OmniSharp/omnisharp-roslyn/pull/1927))
+
## [1.37.0] - 2020-08-18
* Update Roslyn version and tooling to match .NET 5 Preview8 (PR: [#1897](https://github.com/OmniSharp/omnisharp-roslyn/pull/1897))
* Updated lsp library to fix issue with signature help, etc (PR: [#1890](https://github.com/OmniSharp/omnisharp-roslyn/pull/1890))
diff --git a/README.md b/README.md
index 6b5c9253c4..f38be878d0 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
OmniSharp is a .NET development platform based on [Roslyn](https://github.com/dotnet/roslyn) workspaces. It provides project dependencies and C# language services to various IDEs and plugins.
-OmniSharp 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 _net472_ target framework. For platforms other than Windows, OmniSharp ships with an _embedded Mono_ which is based on version _5.18.0_, includes MSBuild _16.3.0_ and is provisioned during the build script. If _Mono_ is globally installed on the system, OmniSharp will prefer it over the embedded version, however version _>=6.4.0_ is required (the lowest version with at least MSBuild _16.3.0_).
+OmniSharp 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 _net472_ target framework. For platforms other than Windows, OmniSharp ships with an _embedded Mono_ which is based on version _6.10.0_, includes MSBuild _16.8.0_ and is provisioned during the build script. If _Mono_ is globally installed on the system, OmniSharp will prefer it over the embedded version, however version _>=6.4.0_ is required (the lowest version with at least MSBuild _16.3.0_).
For Arch Linux users, you need package [mono-msbuild](https://www.archlinux.org/packages/community/x86_64/mono-msbuild/) (>= 16.3).
@@ -64,7 +64,7 @@ For more details, see [Build](https://github.com/OmniSharp/omnisharp-roslyn/blob
### VS Code
-Add the following setting to your [User Settings or Workspace Settings](https://code.visualstudio.com/Docs/customization/userandworkspace).
+Add the following setting to your [User Settings](https://code.visualstudio.com/Docs/customization/userandworkspace).
```JSON
{
@@ -77,7 +77,7 @@ The above option can also be set to:
- "latest" - To consume the latest build from the master branch
- A specific version number like `1.29.2-beta.60`
-In order to be able to attach a debugger, add the following setting:
+In order to be able to attach a debugger, add the following setting to your [User or Workspace settings](https://code.visualstudio.com/Docs/customization/userandworkspace):
```JSON
{
diff --git a/build.cake b/build.cake
index 4e71c97eef..0d32185a5e 100644
--- a/build.cake
+++ b/build.cake
@@ -392,6 +392,10 @@ Task("CreateMSBuildFolder")
source: CombinePaths(msbuildSdkResolverSourceFolder, "Microsoft.DotNet.MSBuildSdkResolver.dll"),
destination: CombinePaths(msbuildSdkResolverTargetFolder, "Microsoft.DotNet.MSBuildSdkResolver.dll"));
+ FileHelper.Copy(
+ source: CombinePaths(msbuildSdkResolverSourceFolder, "Microsoft.DotNet.SdkResolver.dll"),
+ destination: CombinePaths(msbuildSdkResolverTargetFolder, "Microsoft.DotNet.SdkResolver.dll"));
+
if (Platform.Current.IsWindows)
{
CopyDotNetHostResolver(env, "win", "x86", "hostfxr.dll", msbuildSdkResolverTargetFolder, copyToArchSpecificFolder: true);
@@ -906,7 +910,6 @@ Task("Publish")
/// Execute the run script.
///
Task("ExecuteRunScript")
- .WithCriteria(() => !(Platform.Current.IsMacOS && TravisCI.IsRunningOnTravisCI))
.Does(() =>
{
// TODO: Pass configuration into run script to ensure that MSBuild output paths are handled correctly.
diff --git a/build.cmd b/build.cmd
index 47ddeee53f..20899d195e 100644
--- a/build.cmd
+++ b/build.cmd
@@ -1,2 +1,2 @@
@echo off
-powershell.exe -NoProfile -ExecutionPolicy Bypass .\build.ps1 "%*"
+powershell.exe -NoProfile -ExecutionPolicy Bypass %~dp0build.ps1 "%*"
diff --git a/build.json b/build.json
index 094b1f2082..3fe86bbf43 100644
--- a/build.json
+++ b/build.json
@@ -3,7 +3,7 @@
"DotNetChannel": "Preview",
"DotNetVersions": [
"3.1.401",
- "5.0.100-preview.8.20417.9"
+ "5.0.100-rc.1.20452.10"
],
"RequiredMonoVersion": "6.6.0",
"DownloadURL": "https://roslynomnisharp.blob.core.windows.net/ext",
diff --git a/build.ps1 b/build.ps1
index fcd414b119..737c071f71 100644
--- a/build.ps1
+++ b/build.ps1
@@ -42,7 +42,7 @@ http://cakebuild.net
Param(
[parameter(position=0)]
[string]$Target = "Default",
- [string]$Script = "build.cake",
+ [string]$Script = "$PSScriptRoot/build.cake",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Debug",
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
@@ -85,10 +85,6 @@ function MD5HashFile([string] $filePath)
Write-Host "Preparing to run build script..."
-if(!$PSScriptRoot){
- $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-}
-
$TOOLS_DIR = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot "tools"))
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
diff --git a/build/Packages.props b/build/Packages.props
index 122503d415..40989323f3 100644
--- a/build/Packages.props
+++ b/build/Packages.props
@@ -5,8 +5,8 @@
16.6.0
5.2.0
- 3.8.0-1.20363.1
- 2.4.0
+ 3.8.0-3.20451.2
+ 2.4.1
@@ -78,7 +78,7 @@
-
+
diff --git a/src/OmniSharp.Cake/Extensions/ResponseExtensions.cs b/src/OmniSharp.Cake/Extensions/ResponseExtensions.cs
index 2e3bf8772c..ee2fba4ce5 100644
--- a/src/OmniSharp.Cake/Extensions/ResponseExtensions.cs
+++ b/src/OmniSharp.Cake/Extensions/ResponseExtensions.cs
@@ -8,6 +8,7 @@
using OmniSharp.Models.Navigate;
using OmniSharp.Models.MembersTree;
using OmniSharp.Models.Rename;
+using OmniSharp.Models.v1.Completion;
using OmniSharp.Models.V2;
using OmniSharp.Models.V2.CodeActions;
using OmniSharp.Models.V2.CodeStructure;
@@ -27,22 +28,6 @@ public static QuickFixResponse OnlyThisFile(this QuickFixResponse response, stri
var quickFixes = response.QuickFixes.Where(x => PathsAreEqual(x.FileName, fileName));
response.QuickFixes = quickFixes;
return response;
-
- bool PathsAreEqual(string x, string y)
- {
- if (x == null && y == null)
- {
- return true;
- }
- if (x == null || y == null)
- {
- return false;
- }
-
- var comparer = PlatformHelper.IsWindows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
-
- return Path.GetFullPath(x).Equals(Path.GetFullPath(y), comparer);
- }
}
public static Task TranslateAsync(this QuickFixResponse response, OmniSharpWorkspace workspace)
@@ -211,6 +196,38 @@ public static async Task TranslateAsync(this BlockStruct
return response;
}
+ public static async Task TranslateAsync(this CompletionResponse response, OmniSharpWorkspace workspace, CompletionRequest request)
+ {
+ foreach (var item in response.Items)
+ {
+ if (item.AdditionalTextEdits is null)
+ {
+ continue;
+ }
+
+ List additionalTextEdits = null;
+
+ foreach (var additionalTextEdit in item.AdditionalTextEdits)
+ {
+ var (_, change) = await additionalTextEdit.TranslateAsync(workspace, request.FileName);
+
+ // Due to the fact that AdditionalTextEdits return the complete buffer, we can't currently use that in Cake.
+ // Revisit when we have a solution. At this point it's probably just best to remove AdditionalTextEdits.
+ if (change.StartLine < 0)
+ {
+ continue;
+ }
+
+ additionalTextEdits ??= new List();
+ additionalTextEdits.Add(change);
+ }
+
+ item.AdditionalTextEdits = additionalTextEdits;
+ }
+
+ return response;
+ }
+
private static async Task TranslateAsync(this CodeElement element, OmniSharpWorkspace workspace, SimpleFileRequest request)
{
var builder = new CodeElement.Builder
@@ -345,5 +362,21 @@ private static async Task PopulateModificationsAsync(
return (newFileName, change);
}
+
+ private static bool PathsAreEqual(string x, string y)
+ {
+ if (x == null && y == null)
+ {
+ return true;
+ }
+ if (x == null || y == null)
+ {
+ return false;
+ }
+
+ var comparer = PlatformHelper.IsWindows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
+
+ return Path.GetFullPath(x).Equals(Path.GetFullPath(y), comparer);
+ }
}
}
diff --git a/src/OmniSharp.Cake/Services/RequestHandlers/Completion/CompletionHandler.cs b/src/OmniSharp.Cake/Services/RequestHandlers/Completion/CompletionHandler.cs
new file mode 100644
index 0000000000..5de5fe1878
--- /dev/null
+++ b/src/OmniSharp.Cake/Services/RequestHandlers/Completion/CompletionHandler.cs
@@ -0,0 +1,46 @@
+using System.Composition;
+using System.Linq;
+using System.Threading.Tasks;
+using OmniSharp.Cake.Extensions;
+using OmniSharp.Mef;
+using OmniSharp.Models.v1.Completion;
+
+namespace OmniSharp.Cake.Services.RequestHandlers.Completion
+{
+ [Shared]
+ [OmniSharpHandler(OmniSharpEndpoints.Completion, Constants.LanguageNames.Cake)]
+ public class CompletionHandler : CakeRequestHandler
+ {
+ [ImportingConstructor]
+ public CompletionHandler(OmniSharpWorkspace workspace) : base(workspace)
+ {
+ }
+
+ protected override Task TranslateResponse(CompletionResponse response, CompletionRequest request)
+ {
+ return response.TranslateAsync(Workspace, request);
+ }
+ }
+
+ [Shared]
+ [OmniSharpHandler(OmniSharpEndpoints.CompletionResolve, Constants.LanguageNames.Cake)]
+ public class CompletionResolveHandler : CakeRequestHandler
+ {
+ [ImportingConstructor]
+ public CompletionResolveHandler(OmniSharpWorkspace workspace) : base(workspace)
+ {
+ }
+
+ protected override Task TranslateResponse(CompletionResolveResponse response, CompletionResolveRequest request)
+ {
+ // Due to the fact that AdditionalTextEdits return the complete buffer, we can't currently use that in Cake.
+ // Revisit when we have a solution. At this point it's probably just best to remove AdditionalTextEdits.
+ if (response.Item is object)
+ {
+ response.Item.AdditionalTextEdits = null;
+ }
+
+ return Task.FromResult(response);
+ }
+ }
+}
diff --git a/src/OmniSharp.Cake/Services/RequestHandlers/QuickInfoHandler.cs b/src/OmniSharp.Cake/Services/RequestHandlers/QuickInfoHandler.cs
new file mode 100644
index 0000000000..b3aa32f193
--- /dev/null
+++ b/src/OmniSharp.Cake/Services/RequestHandlers/QuickInfoHandler.cs
@@ -0,0 +1,16 @@
+using System.Composition;
+using OmniSharp.Mef;
+using OmniSharp.Models;
+
+namespace OmniSharp.Cake.Services.RequestHandlers
+{
+ [Shared]
+ [OmniSharpHandler(OmniSharpEndpoints.QuickInfo, Constants.LanguageNames.Cake)]
+ public class QuickInfoHandler : CakeRequestHandler
+ {
+ [ImportingConstructor]
+ public QuickInfoHandler(OmniSharpWorkspace workspace) : base(workspace)
+ {
+ }
+ }
+}
diff --git a/src/OmniSharp.LanguageServerProtocol/Handlers/OmniSharpCompletionHandler.cs b/src/OmniSharp.LanguageServerProtocol/Handlers/OmniSharpCompletionHandler.cs
index 1759499372..dfa8b1b37e 100644
--- a/src/OmniSharp.LanguageServerProtocol/Handlers/OmniSharpCompletionHandler.cs
+++ b/src/OmniSharp.LanguageServerProtocol/Handlers/OmniSharpCompletionHandler.cs
@@ -27,10 +27,10 @@ public static IEnumerable Enumerate(RequestHandlers handlers)
private static readonly IDictionary _kind = new Dictionary{
// types
{ "Class", CompletionItemKind.Class },
- { "Delegate", CompletionItemKind.Class }, // need a better option for this.
+ { "Delegate", CompletionItemKind.Function },
{ "Enum", CompletionItemKind.Enum },
{ "Interface", CompletionItemKind.Interface },
- { "Struct", CompletionItemKind.Class }, // TODO: Is struct missing from enum?
+ { "Struct", CompletionItemKind.Struct },
// variables
{ "Local", CompletionItemKind.Variable },
@@ -38,15 +38,15 @@ public static IEnumerable Enumerate(RequestHandlers handlers)
{ "RangeVariable", CompletionItemKind.Variable },
// members
- { "Const", CompletionItemKind.Value }, // TODO: Is const missing from enum?
+ { "Const", CompletionItemKind.Constant },
{ "EnumMember", CompletionItemKind.Enum },
- { "Event", CompletionItemKind.Function }, // TODO: Is event missing from enum?
+ { "Event", CompletionItemKind.Event },
{ "Field", CompletionItemKind.Field },
{ "Method", CompletionItemKind.Method },
{ "Property", CompletionItemKind.Property },
// other stuff
- { "Label", CompletionItemKind.Unit }, // need a better option for this.
+ { "Label", CompletionItemKind.Text },
{ "Keyword", CompletionItemKind.Keyword },
{ "Namespace", CompletionItemKind.Module }
};
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Completion/CompletionService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Completion/CompletionService.cs
index e10f871fee..a95e2d6ad6 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Completion/CompletionService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Completion/CompletionService.cs
@@ -59,7 +59,7 @@ public class CompletionService :
{ WellKnownTags.Keyword, CompletionItemKind.Keyword },
{ WellKnownTags.Label, CompletionItemKind.Text },
{ WellKnownTags.Local, CompletionItemKind.Variable },
- { WellKnownTags.Namespace, CompletionItemKind.Text },
+ { WellKnownTags.Namespace, CompletionItemKind.Module },
{ WellKnownTags.Method, CompletionItemKind.Method },
{ WellKnownTags.Module, CompletionItemKind.Module },
{ WellKnownTags.Operator, CompletionItemKind.Operator },
@@ -174,6 +174,16 @@ public async Task Handle(CompletionRequest request)
string providerName = completion.GetProviderName();
switch (providerName)
{
+ case CompletionItemExtensions.EmeddedLanguageCompletionProvider:
+ // The Regex completion provider can change escapes based on whether
+ // we're in a verbatim string or not
+ {
+ CompletionChange change = await completionService.GetChangeAsync(document, completion);
+ Debug.Assert(typedSpan == change.TextChange.Span);
+ insertText = change.TextChange.NewText!;
+ }
+ break;
+
case CompletionItemExtensions.InternalsVisibleToCompletionProvider:
// The IVT completer doesn't add extra things before the completion
// span, only assembly keys at the end if they exist.
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs
index 6ece193da3..e8f828aa6a 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/CompletionItemExtensions.cs
@@ -26,6 +26,7 @@ internal static class CompletionItemExtensions
internal const string XmlDocCommentCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.XmlDocCommentCompletionProvider";
internal const string TypeImportCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.TypeImportCompletionProvider";
internal const string ExtensionMethodImportCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.ExtensionMethodImportCompletionProvider";
+ internal const string EmeddedLanguageCompletionProvider = "Microsoft.CodeAnalysis.CSharp.Completion.Providers.EmbeddedLanguageCompletionProvider";
private const string ProviderName = nameof(ProviderName);
private const string SymbolCompletionItem = "Microsoft.CodeAnalysis.Completion.Providers.SymbolCompletionItem";
private const string SymbolKind = nameof(SymbolKind);
@@ -69,8 +70,9 @@ internal static Task GetChangeAsync(
CompletionItem item,
TextSpan completionListSpan,
char? commitCharacter = null,
+ bool disallowAddingImports = false,
CancellationToken cancellationToken = default)
- => (Task)_getChangeAsync.Invoke(completionService, new object[] { document, item, completionListSpan, commitCharacter, cancellationToken });
+ => (Task)_getChangeAsync.Invoke(completionService, new object[] { document, item, completionListSpan, commitCharacter, disallowAddingImports, cancellationToken });
public static async Task> GetCompletionSymbolsAsync(this CompletionItem completionItem, IEnumerable recommendedSymbols, Document document)
{
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs
index b042f092d8..82199418bd 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Intellisense/IntellisenseService.cs
@@ -15,6 +15,7 @@
namespace OmniSharp.Roslyn.CSharp.Services.Intellisense
{
+ [Obsolete("Please use CompletionService.")]
[OmniSharpHandler(OmniSharpEndpoints.AutoComplete, LanguageNames.CSharp)]
public class IntellisenseService : IRequestHandler>
{
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Navigation/FindImplementationsService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Navigation/FindImplementationsService.cs
index 2d8e198390..d2f40a73cd 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Navigation/FindImplementationsService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Navigation/FindImplementationsService.cs
@@ -39,23 +39,25 @@ public async Task Handle(FindImplementationsRequest request)
var quickFixes = new List();
var symbol = await SymbolFinder.FindSymbolAtPositionAsync(semanticModel, position, _workspace);
- // SymbolFinder.FindImplementationsAsync will not include the method overrides
- var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution);
- foreach (var implementation in implementations)
+ if (symbol.IsInterfaceType() || symbol.IsImplementableMember())
{
- quickFixes.Add(implementation, _workspace);
-
- if (implementation.IsOverridable())
+ // SymbolFinder.FindImplementationsAsync will not include the method overrides
+ var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution);
+ foreach (var implementation in implementations)
{
- var overrides = await SymbolFinder.FindOverridesAsync(implementation, _workspace.CurrentSolution);
- quickFixes.AddRange(overrides, _workspace);
+ quickFixes.Add(implementation, _workspace);
+
+ if (implementation.IsOverridable())
+ {
+ var overrides = await SymbolFinder.FindOverridesAsync(implementation, _workspace.CurrentSolution);
+ quickFixes.AddRange(overrides, _workspace);
+ }
}
}
-
- // for types also include derived classes
- // for other symbols, find overrides and include those
- if (symbol is INamedTypeSymbol namedTypeSymbol)
+ else if (symbol is INamedTypeSymbol namedTypeSymbol)
{
+ // for types also include derived classes
+ // for other symbols, find overrides and include those
var derivedTypes = await SymbolFinder.FindDerivedClassesAsync(namedTypeSymbol, _workspace.CurrentSolution);
quickFixes.AddRange(derivedTypes, _workspace);
}
diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/V2/RunCodeActionService.cs b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/V2/RunCodeActionService.cs
index 7b6229b620..9a362910ee 100644
--- a/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/V2/RunCodeActionService.cs
+++ b/src/OmniSharp.Roslyn.CSharp/Services/Refactoring/V2/RunCodeActionService.cs
@@ -68,6 +68,11 @@ public override async Task Handle(RunCodeActionRequest re
changes.AddRange(fileChangesResult.FileChanges);
solution = fileChangesResult.Solution;
}
+ else
+ {
+ o.Apply(this.Workspace, CancellationToken.None);
+ solution = this.Workspace.CurrentSolution;
+ }
if (request.WantsAllCodeActionOperations)
{
diff --git a/src/OmniSharp.Roslyn/Extensions/SymbolExtensions.cs b/src/OmniSharp.Roslyn/Extensions/SymbolExtensions.cs
index f88079657a..df584c08e1 100644
--- a/src/OmniSharp.Roslyn/Extensions/SymbolExtensions.cs
+++ b/src/OmniSharp.Roslyn/Extensions/SymbolExtensions.cs
@@ -297,5 +297,38 @@ internal static string GetFilePathForExternalSymbol(this ISymbol symbol, Project
}
private static string Folderize(string path) => string.Join("/", path.Split('.'));
+
+ public static bool IsInterfaceType(this ISymbol symbol) => (symbol as ITypeSymbol)?.IsInterfaceType() == true;
+
+ public static bool IsInterfaceType(this ITypeSymbol symbol) => symbol?.TypeKind == TypeKind.Interface;
+
+ public static bool IsImplementableMember(this ISymbol symbol)
+ {
+ if (symbol?.ContainingType?.TypeKind == TypeKind.Interface)
+ {
+ if (symbol.Kind == SymbolKind.Event)
+ {
+ return true;
+ }
+
+ if (symbol.Kind == SymbolKind.Property)
+ {
+ return true;
+ }
+
+ if (symbol.Kind == SymbolKind.Method)
+ {
+ var methodSymbol = (IMethodSymbol)symbol;
+ if (methodSymbol.MethodKind == MethodKind.Ordinary ||
+ methodSymbol.MethodKind == MethodKind.PropertyGet ||
+ methodSymbol.MethodKind == MethodKind.PropertySet)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
}
diff --git a/test-assets/test-projects/Net50Project/global.json b/test-assets/test-projects/Net50Project/global.json
index fd901084a9..53424aca80 100644
--- a/test-assets/test-projects/Net50Project/global.json
+++ b/test-assets/test-projects/Net50Project/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "5.0.100-preview.8.20417.9"
+ "version": "5.0.100-rc.1.20452.10"
}
}
diff --git a/tests/OmniSharp.Cake.Tests/CompletionFacts.cs b/tests/OmniSharp.Cake.Tests/CompletionFacts.cs
new file mode 100644
index 0000000000..83812f57b3
--- /dev/null
+++ b/tests/OmniSharp.Cake.Tests/CompletionFacts.cs
@@ -0,0 +1,234 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using OmniSharp.Cake.Services.RequestHandlers.Completion;
+using OmniSharp.Models.UpdateBuffer;
+using OmniSharp.Models.v1.Completion;
+using TestUtility;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OmniSharp.Cake.Tests
+{
+ public class CompletionFacts : CakeSingleRequestHandlerTestFixture
+ {
+ private const int ImportCompletionTimeout = 1000;
+ private readonly ILogger _logger;
+
+ public CompletionFacts(ITestOutputHelper testOutput) : base(testOutput)
+ {
+ _logger = LoggerFactory.CreateLogger();
+ }
+
+ protected override string EndpointName => OmniSharpEndpoints.Completion;
+
+ [Fact]
+ public async Task ShouldGetCompletionFromHostObject()
+ {
+ const string input = @"TaskSe$$";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+ var completions = await FindCompletionsAsync(fileName, input, host);
+
+ Assert.Contains("TaskSetup", completions.Items.Select(c => c.Label));
+ Assert.Contains("TaskSetup", completions.Items.Select(c => c.InsertText));
+ }
+ }
+
+ [Fact]
+ public async Task ShouldGetCompletionFromDSL()
+ {
+ const string input =
+ @"Task(""Test"")
+ .Does(() => {
+ Inform$$
+ });";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+ var completions = await FindCompletionsAsync(fileName, input, host);
+
+ Assert.Contains("Information", completions.Items.Select(c => c.Label));
+ Assert.Contains("Information", completions.Items.Select(c => c.InsertText));
+ }
+ }
+
+ [Fact]
+ public async Task ShouldResolveFromDSL()
+ {
+ const string input =
+ @"Task(""Test"")
+ .Does(() => {
+ Inform$$
+ });";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+ var completion = (await FindCompletionsAsync(fileName, input, host))
+ .Items.First(x => x.Preselect && x.InsertText == "Information");
+
+ var resolved = await ResolveCompletionAsync(completion, host);
+
+ Assert.StartsWith(
+ "```csharp\nvoid Information(string format, params object[] args)",
+ resolved.Item?.Documentation);
+ }
+ }
+
+ [Fact]
+ public async Task ShouldRemoveAdditionalTextEditsFromResolvedCompletions()
+ {
+ const string input = @"var regex = new Rege$$";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory,
+ new[] { new KeyValuePair("RoslynExtensionsOptions:EnableImportCompletion", "true") }))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+
+ // First completion request should kick off the task to update the completion cache.
+ var completions = await FindCompletionsAsync(fileName, input, host);
+ Assert.True(completions.IsIncomplete);
+ Assert.DoesNotContain("Regex", completions.Items.Select(c => c.InsertText));
+
+ // Populating the completion cache should take no more than a few ms, don't let it take too
+ // long
+ var cts = new CancellationTokenSource(millisecondsDelay: ImportCompletionTimeout);
+ await Task.Run(async () =>
+ {
+ while (completions.IsIncomplete)
+ {
+ completions = await FindCompletionsAsync(fileName, input, host);
+ cts.Token.ThrowIfCancellationRequested();
+ }
+ }, cts.Token);
+
+ Assert.False(completions.IsIncomplete);
+ Assert.Contains("Regex", completions.Items.Select(c => c.InsertText));
+
+ var completion = completions.Items.First(c => c.InsertText == "Regex");
+ var resolved = await ResolveCompletionAsync(completion, host);
+
+ // Due to the fact that AdditionalTextEdits return the complete buffer, we can't currently use that in Cake.
+ // Revisit when we have a solution. At this point it's probably just best to remove AdditionalTextEdits.
+ Assert.Null(resolved.Item.AdditionalTextEdits);
+ }
+ }
+
+ [Fact]
+ public async Task ShouldGetAdditionalTextEditsFromOverrideCompletion()
+ {
+ const string source = @"
+class Foo
+{
+ public virtual void Test(string text) {}
+ public virtual void Test(string text, string moreText) {}
+}
+
+class FooChild : Foo
+{
+ override $$
+}
+";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+ var completions = await FindCompletionsAsync(fileName, source, host);
+ Assert.Equal(
+ new[]
+ {
+ "Equals(object obj)", "GetHashCode()", "Test(string text)",
+ "Test(string text, string moreText)", "ToString()"
+ },
+ completions.Items.Select(c => c.Label));
+ Assert.Equal(new[]
+ {
+ "Equals(object obj)\n {\n return base.Equals(obj);$0\n \\}",
+ "GetHashCode()\n {\n return base.GetHashCode();$0\n \\}",
+ "Test(string text)\n {\n base.Test(text);$0\n \\}",
+ "Test(string text, string moreText)\n {\n base.Test(text, moreText);$0\n \\}",
+ "ToString()\n {\n return base.ToString();$0\n \\}"
+ },
+ completions.Items.Select(c => c.InsertText));
+
+ Assert.Equal(new[]
+ {
+ "public override bool",
+ "public override int",
+ "public override void",
+ "public override void",
+ "public override string"
+ },
+ completions.Items.Select(c => c.AdditionalTextEdits.Single().NewText));
+
+ Assert.All(completions.Items.Select(c => c.AdditionalTextEdits.Single()),
+ r =>
+ {
+ Assert.Equal(9, r.StartLine);
+ Assert.Equal(4, r.StartColumn);
+ Assert.Equal(9, r.EndLine);
+ Assert.Equal(12, r.EndColumn);
+ });
+
+ Assert.All(completions.Items, c => Assert.Equal(InsertTextFormat.Snippet, c.InsertTextFormat));
+ }
+ }
+
+ private async Task FindCompletionsAsync(string filename, string source, OmniSharpTestHost host, char? triggerChar = null, TestFile[] additionalFiles = null)
+ {
+ var testFile = new TestFile(filename, source);
+
+ var files = new[] { testFile };
+ if (additionalFiles is object)
+ {
+ files = files.Concat(additionalFiles).ToArray();
+ }
+
+ host.AddFilesToWorkspace(files);
+ var point = testFile.Content.GetPointFromPosition();
+
+ var request = new CompletionRequest
+ {
+ Line = point.Line,
+ Column = point.Offset,
+ FileName = testFile.FileName,
+ Buffer = testFile.Content.Code,
+ CompletionTrigger = triggerChar is object ? CompletionTriggerKind.TriggerCharacter : CompletionTriggerKind.Invoked,
+ TriggerCharacter = triggerChar
+ };
+
+ var updateBufferRequest = new UpdateBufferRequest
+ {
+ Buffer = request.Buffer,
+ Column = request.Column,
+ FileName = request.FileName,
+ Line = request.Line,
+ FromDisk = false
+ };
+
+ await GetUpdateBufferHandler(host).Handle(updateBufferRequest);
+
+ var requestHandler = GetRequestHandler(host);
+
+ return await requestHandler.Handle(request);
+ }
+
+ private static async Task ResolveCompletionAsync(CompletionItem completionItem, OmniSharpTestHost testHost)
+ => await GetResolveHandler(testHost).Handle(new CompletionResolveRequest { Item = completionItem });
+
+ private static CompletionResolveHandler GetResolveHandler(OmniSharpTestHost host)
+ => host.GetRequestHandler(OmniSharpEndpoints.CompletionResolve, Constants.LanguageNames.Cake);
+ }
+}
diff --git a/tests/OmniSharp.Cake.Tests/QuickInfoFacts.cs b/tests/OmniSharp.Cake.Tests/QuickInfoFacts.cs
new file mode 100644
index 0000000000..0c5ac6040a
--- /dev/null
+++ b/tests/OmniSharp.Cake.Tests/QuickInfoFacts.cs
@@ -0,0 +1,81 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using OmniSharp.Cake.Services.RequestHandlers;
+using OmniSharp.Cake.Services.RequestHandlers.Completion;
+using OmniSharp.Models;
+using OmniSharp.Models.UpdateBuffer;
+using OmniSharp.Models.v1.Completion;
+using TestUtility;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OmniSharp.Cake.Tests
+{
+ public class QuickInfoFacts : CakeSingleRequestHandlerTestFixture
+ {
+ private readonly ILogger _logger;
+
+ public QuickInfoFacts(ITestOutputHelper testOutput) : base(testOutput)
+ {
+ _logger = LoggerFactory.CreateLogger();
+ }
+
+ protected override string EndpointName => OmniSharpEndpoints.QuickInfo;
+
+ [Fact]
+ public async Task ShouldGetQuickInfo()
+ {
+ const string input = "Informa$$tion(\"Hello\");";
+
+ using (var testProject = await TestAssets.Instance.GetTestProjectAsync("CakeProject", shadowCopy : false))
+ using (var host = CreateOmniSharpHost(testProject.Directory))
+ {
+ var fileName = Path.Combine(testProject.Directory, "build.cake");
+ var quickInfo = await GetQuickInfo(fileName, input, host);
+
+ Assert.StartsWith("```csharp\nvoid Information(string value)", quickInfo.Markdown);
+ }
+ }
+
+ private async Task GetQuickInfo(string filename, string source, OmniSharpTestHost host, char? triggerChar = null, TestFile[] additionalFiles = null)
+ {
+ var testFile = new TestFile(filename, source);
+
+ var files = new[] { testFile };
+ if (additionalFiles is object)
+ {
+ files = files.Concat(additionalFiles).ToArray();
+ }
+
+ host.AddFilesToWorkspace(files);
+ var point = testFile.Content.GetPointFromPosition();
+
+ var request = new QuickInfoRequest
+ {
+ Line = point.Line,
+ Column = point.Offset,
+ FileName = testFile.FileName,
+ Buffer = testFile.Content.Code
+ };
+
+ var updateBufferRequest = new UpdateBufferRequest
+ {
+ Buffer = request.Buffer,
+ Column = request.Column,
+ FileName = request.FileName,
+ Line = request.Line,
+ FromDisk = false
+ };
+
+ await GetUpdateBufferHandler(host).Handle(updateBufferRequest);
+
+ var requestHandler = GetRequestHandler(host);
+
+ return await requestHandler.Handle(request);
+ }
+ }
+}
diff --git a/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs b/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs
index 9735ac301c..68f3a2c612 100644
--- a/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs
+++ b/tests/OmniSharp.MSBuild.Tests/ProjectLoadListenerTests.cs
@@ -1,16 +1,8 @@
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;
@@ -98,12 +90,10 @@ public async Task The_target_framework_is_emitted()
var expectedTFM = "netcoreapp2.1";
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal(emitter.ReceivedMessages[0].TargetFrameworks.First(), expectedTFM);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal(emitter.ReceivedMessages[0].TargetFrameworks.First(), expectedTFM);
}
[Fact]
@@ -112,13 +102,11 @@ public async Task If_there_is_a_solution_file_the_project_guid_present_in_it_is_
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectAndSolution"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- var expectedGuid = "A4C2694D-AEB4-4CB1-8951-5290424EF883".ToLower();
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal(emitter.ReceivedMessages[0].ProjectId, expectedGuid);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectAndSolution");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ var expectedGuid = "A4C2694D-AEB4-4CB1-8951-5290424EF883".ToLower();
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal(emitter.ReceivedMessages[0].ProjectId, expectedGuid);
}
[Fact]
@@ -127,14 +115,12 @@ public async Task If_there_is_no_solution_file_the_hash_of_project_file_content_
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- var projectFileContent = File.ReadAllText(Directory.GetFiles(testProject.Directory, "*.csproj").Single());
- var expectedGuid = GetHashedReference($"Filename: HelloWorld.csproj\n{projectFileContent}");
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal(emitter.ReceivedMessages[0].ProjectId, expectedGuid);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ var projectFileContent = File.ReadAllText(Directory.GetFiles(testProject.Directory, "*.csproj").Single());
+ var expectedGuid = GetHashedReference($"Filename: HelloWorld.csproj\n{projectFileContent}");
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal(emitter.ReceivedMessages[0].ProjectId, expectedGuid);
}
[Fact]
@@ -142,16 +128,12 @@ public async Task Given_a_restored_project_the_references_are_emitted()
{
var emitter = new ProjectLoadTestEventEmitter();
- 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, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.NotEmpty(emitter.ReceivedMessages[0].References.Where(reference => reference == GetHashedReference("system.core")));
- }
- }
+ 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, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.NotEmpty(emitter.ReceivedMessages[0].References.Where(reference => reference == GetHashedReference("system.core")));
}
@@ -160,15 +142,13 @@ public async Task If_there_are_multiple_target_frameworks_they_are_emitted()
{
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectWithMultiTFMLib/Lib"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- var tfm = emitter.ReceivedMessages[0].TargetFrameworks.ToArray();
- Assert.Equal(2, tfm.Count());
- Assert.Equal("netstandard1.3", tfm[0]);
- Assert.Equal("netstandard2.0", tfm[1]);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectWithMultiTFMLib/Lib");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ var tfm = emitter.ReceivedMessages[0].TargetFrameworks.ToArray();
+ Assert.Equal(2, tfm.Count());
+ Assert.Equal("netstandard1.3", tfm[0]);
+ Assert.Equal("netstandard2.0", tfm[1]);
}
[Fact]
@@ -177,13 +157,11 @@ public async Task The_hashed_references_of_the_source_files_are_emitted()
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.Single(emitter.ReceivedMessages[0].FileExtensions);
- Assert.Equal(emitter.ReceivedMessages[0].FileExtensions.First(), GetHashedFileExtension(".cs"));
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("HelloWorld");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Single(emitter.ReceivedMessages[0].FileExtensions);
+ Assert.Equal(emitter.ReceivedMessages[0].FileExtensions.First(), GetHashedFileExtension(".cs"));
}
[Fact]
@@ -192,12 +170,10 @@ public async Task The_output_kind_is_emitted()
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal((int)OutputKind.ConsoleApplication, emitter.ReceivedMessages[0].OutputKind);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal((int)OutputKind.ConsoleApplication, emitter.ReceivedMessages[0].OutputKind);
}
[Fact]
@@ -206,12 +182,10 @@ public async Task The_correct_project_capablities_is_emitted()
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal("GenerateDocumentationFile CSharp Managed ReferencesFolder LanguageService RelativePathDerivedDefaultNamespace AssemblyReferences COMReferences ProjectReferences SharedProjectReferences OutputGroups AllTargetOutputGroups VisualStudioWellKnownOutputGroups SingleFileGenerators DeclaredSourceItems UserSourceItems BuildWindowsDesktopTarget CrossPlatformExecutable Pack", string.Join(" ", emitter.ReceivedMessages[0].ProjectCapabilities));
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal("GenerateDocumentationFile CSharp Managed ReferencesFolder LanguageService RelativePathDerivedDefaultNamespace AssemblyReferences COMReferences ProjectReferences SharedProjectReferences OutputGroups AllTargetOutputGroups VisualStudioWellKnownOutputGroups SingleFileGenerators DeclaredSourceItems UserSourceItems BuildWindowsDesktopTarget CrossPlatformExecutable Pack", string.Join(" ", emitter.ReceivedMessages[0].ProjectCapabilities));
}
[Fact]
@@ -220,12 +194,10 @@ public async Task The_correct_sdk_version_is_emitted()
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Single(emitter.ReceivedMessages);
- Assert.Equal(GetHashedFileExtension("3.1.401"), emitter.ReceivedMessages[0].SdkVersion);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("NetCore31Project");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Single(emitter.ReceivedMessages);
+ Assert.Equal(GetHashedFileExtension("3.1.401"), emitter.ReceivedMessages[0].SdkVersion);
}
[Fact]
@@ -234,12 +206,10 @@ public async Task The_correct_sdk_version_is_emitted_2()
// Arrange
var emitter = new ProjectLoadTestEventEmitter();
- using (var testProject = await TestAssets.Instance.GetTestProjectAsync("Net50Project"))
- using (var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory)))
- {
- Assert.Equal(2, emitter.ReceivedMessages.Length);
- Assert.Equal(GetHashedFileExtension("5.0.100-preview.8.20417.9"), emitter.ReceivedMessages[0].SdkVersion);
- }
+ using var testProject = await TestAssets.Instance.GetTestProjectAsync("Net50Project");
+ using var host = CreateMSBuildTestHost(testProject.Directory, emitter.AsExportDescriptionProvider(LoggerFactory));
+ Assert.Equal(2, emitter.ReceivedMessages.Length);
+ Assert.Equal(GetHashedFileExtension("5.0.100-rc.1.20452.10"), emitter.ReceivedMessages[0].SdkVersion);
}
private string GetHashedFileExtension(string fileExtension)
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/CompletionFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/CompletionFacts.cs
index 917fb0dec2..56b8f607bd 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/CompletionFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/CompletionFacts.cs
@@ -1336,6 +1336,48 @@ public async Task InternalsVisibleToCompletionSkipsMiscProject()
Assert.Equal("AssemblyNameVal", completions.Items[0].InsertText);
}
+ [ConditionalTheory(typeof(WindowsOnly))]
+ [InlineData("dummy.cs")]
+ [InlineData("dummy.csx")]
+ public async Task RegexCompletionInNormalString(string filename)
+ {
+ const string input = @"
+using System.Text.RegularExpressions;
+class Foo
+{
+ public void M()
+ {
+ _ = new Regex(""$$"");
+ }
+}";
+
+ var completions = await FindCompletionsAsync(filename, input, SharedOmniSharpTestHost);
+ var aCompletion = completions.Items.First(c => c.Label == @"\A");
+ Assert.NotNull(aCompletion);
+ Assert.Equal(@"\\A", aCompletion.InsertText);
+ }
+
+ [ConditionalTheory(typeof(WindowsOnly))]
+ [InlineData("dummy.cs")]
+ [InlineData("dummy.csx")]
+ public async Task RegexCompletionInVerbatimString(string filename)
+ {
+ const string input = @"
+using System.Text.RegularExpressions;
+class Foo
+{
+ public void M()
+ {
+ _ = new Regex(@""$$"");
+ }
+}";
+
+ var completions = await FindCompletionsAsync(filename, input, SharedOmniSharpTestHost);
+ var aCompletion = completions.Items.First(c => c.Label == @"\A");
+ Assert.NotNull(aCompletion);
+ Assert.Equal(@"\A", aCompletion.InsertText);
+ }
+
private CompletionService GetCompletionService(OmniSharpTestHost host)
=> host.GetRequestHandler(EndpointName);
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
index d53baa0c6f..909d7c9895 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/IntellisenseFacts.cs
@@ -475,6 +475,33 @@ void M()
Assert.Contains(@"The ""G"" standard format specifier", gStandardCompletion.Description);
}
+ [ConditionalTheory(typeof(WindowsOnly))]
+ [InlineData("dummy.cs")]
+ [InlineData("dummy.csx")]
+ public async Task Embedded_language_completion_provider_for_regex(string filename)
+ {
+ const string source = @"
+ using System;
+ using System.Text.RegularExpressions;
+ class C
+ {
+ void M()
+ {
+ var r = Regex.Match(""foo"", ""$$""
+ }
+ }
+ ";
+
+ var completions = await FindCompletionsAsync(filename, source);
+
+ Assert.NotEmpty(completions);
+
+ var wCompletion = completions.FirstOrDefault(x => x.CompletionText == @"\w");
+ Assert.NotNull(wCompletion);
+ Assert.Equal("word character", wCompletion.DisplayText);
+ Assert.Contains(@"matches any word character", wCompletion.Description);
+ }
+
[Fact]
public async Task Scripting_by_default_returns_completions_for_CSharp7_1()
{
diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/OmniSharp.Roslyn.CSharp.Tests.csproj b/tests/OmniSharp.Roslyn.CSharp.Tests/OmniSharp.Roslyn.CSharp.Tests.csproj
index b62c699c6e..fbddead4eb 100644
--- a/tests/OmniSharp.Roslyn.CSharp.Tests/OmniSharp.Roslyn.CSharp.Tests.csproj
+++ b/tests/OmniSharp.Roslyn.CSharp.Tests/OmniSharp.Roslyn.CSharp.Tests.csproj
@@ -4,6 +4,7 @@
net472
AnyCPU
true
+ CS0618
diff --git a/tools/packages.config b/tools/packages.config
index 49c9d0c1b7..3108240628 100644
--- a/tools/packages.config
+++ b/tools/packages.config
@@ -2,32 +2,32 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+