Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,32 @@ void M(object o)
}
""", "customers");

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79417")]
public Task TestNestedParameter1()
=> VerifyItemExistsAsync("""
class C
{
void M(MyWidget myWidget)
{
void LocalFunction(MyWidget $$) { }
}
}
""", "myWidget");

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79417")]
public Task TestNestedParameter2()
=> VerifyItemExistsAsync("""
class MyWidget { }
class C(MyWidget myWidget)
{
class D(MyWidget $$) { }
}
""", "myWidget");

#if false

#endif

private static NamingStylePreferences MultipleCamelCaseLocalRules()
{
var styles = new[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.ObsoleteSymbol;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ObsoleteSymbol;
Expand All @@ -14,6 +16,9 @@ public sealed class CSharpObsoleteSymbolTests : AbstractObsoleteSymbolTests
protected override EditorTestWorkspace CreateWorkspace(string markup)
=> EditorTestWorkspace.CreateCSharp(markup);

private new Task TestAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup)
=> base.TestAsync(markup);

[Theory]
[InlineData("class")]
[InlineData("struct")]
Expand Down Expand Up @@ -183,4 +188,15 @@ void Method()
}
}
""");

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79413")]
public Task TestObsoleteFeatureAttribute()
=> TestAsync(
"""
[System.Obsolete]
[System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute("This is an obsolete feature.")]
static class ObsoleteType
{
}
""");
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers;

[ExportCompletionProvider(nameof(DeclarationNameCompletionProvider), LanguageNames.CSharp)]
[ExportCompletionProvider(nameof(DeclarationNameCompletionProvider), LanguageNames.CSharp), Shared]
[ExtensionOrder(After = nameof(TupleNameCompletionProvider))]
[Shared]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed partial class DeclarationNameCompletionProvider([ImportMany] IEnumerable<Lazy<IDeclarationNameRecommender, OrderableMetadata>> recommenders) : LSPCompletionProvider
internal sealed partial class DeclarationNameCompletionProvider(
[ImportMany] IEnumerable<Lazy<IDeclarationNameRecommender, OrderableMetadata>> recommenders) : LSPCompletionProvider
{
private ImmutableArray<Lazy<IDeclarationNameRecommender, OrderableMetadata>> Recommenders { get; } = [.. ExtensionOrderer.Order(recommenders)];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers.DeclarationName;

[ExportDeclarationNameRecommender(nameof(DeclarationNameRecommender)), Shared]
internal sealed partial class DeclarationNameRecommender : IDeclarationNameRecommender
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed partial class DeclarationNameRecommender() : IDeclarationNameRecommender
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public DeclarationNameRecommender()
{ }

public async Task<ImmutableArray<(string name, Glyph glyph)>> ProvideRecommendedNamesAsync(
CompletionContext completionContext,
Document document,
Expand Down Expand Up @@ -255,9 +252,9 @@ static void ProcessRules(
context.TargetToken.GetRequiredParent(),
container: null,
baseName: name,
filter: s => IsRelevantSymbolKind(s),
filter: IsRelevantSymbolKind,
usedNames: [],
cancellationToken: cancellationToken);
cancellationToken);

if (seenUniqueNames.Add(uniqueName.Text))
{
Expand Down Expand Up @@ -331,9 +328,5 @@ static ImmutableArray<IMethodSymbol> GetOverloads(INamedTypeSymbol namedType, Ba
/// Only relevant if symbol could cause a conflict with a local variable.
/// </summary>
private static bool IsRelevantSymbolKind(ISymbol symbol)
{
return symbol.Kind is SymbolKind.Local or
SymbolKind.Parameter or
SymbolKind.RangeVariable;
}
=> symbol.Kind is SymbolKind.Local or SymbolKind.Parameter or SymbolKind.RangeVariable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -644,14 +644,25 @@ protected virtual RoslynLanguageServer CreateLanguageServer(Stream inputStream,

public async Task<Document> GetDocumentAsync(DocumentUri uri)
{
var document = await GetCurrentSolution().GetDocumentAsync(new LSP.TextDocumentIdentifier { DocumentUri = uri }, CancellationToken.None).ConfigureAwait(false);
var textDocument = await GetTextDocumentAsync(uri).ConfigureAwait(false);
if (textDocument is not Document document)
{
throw new InvalidOperationException($"Found TextDocument with {uri} in solution, but it is not a Document");
}

return document;
}

public async Task<TextDocument> GetTextDocumentAsync(DocumentUri uri)
{
var document = await GetCurrentSolution().GetTextDocumentAsync(new LSP.TextDocumentIdentifier { DocumentUri = uri }, CancellationToken.None).ConfigureAwait(false);
Contract.ThrowIfNull(document, $"Unable to find document with {uri} in solution");
return document;
}

public async Task<SourceText> GetDocumentTextAsync(DocumentUri uri)
{
var document = await GetDocumentAsync(uri).ConfigureAwait(false);
var document = await GetTextDocumentAsync(uri).ConfigureAwait(false);
return await document.GetTextAsync(CancellationToken.None).ConfigureAwait(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override ValueTask<ImmutableArray<IDiagnosticSource>> GetOrderedDiagno
// Only consider open documents here (and only closed ones in the WorkspacePullDiagnosticHandler). Each
// handler treats those as separate worlds that they are responsible for.
var identifier = GetTextDocumentIdentifier(diagnosticsParams);
if (identifier is null || context.Document is null)
if (identifier is null || context.TextDocument is null)
{
context.TraceDebug("Ignoring diagnostics request because no text document was provided");
return new([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private protected static async Task InsertTextAsync(
await testLspServer.InsertTextAsync(document.GetURI(), (lineInfo.Start.Line, lineInfo.Start.Character, text));
}

private protected static Task OpenDocumentAsync(TestLspServer testLspServer, Document document) => testLspServer.OpenDocumentAsync(document.GetURI());
private protected static Task OpenDocumentAsync(TestLspServer testLspServer, TextDocument document) => testLspServer.OpenDocumentAsync(document.GetURI());

private protected static Task<ImmutableArray<TestDiagnosticResult>> RunGetDocumentPullDiagnosticsAsync(
TestLspServer testLspServer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
Expand All @@ -22,6 +28,32 @@ public AdditionalFileDiagnosticsTests(ITestOutputHelper testOutputHelper) : base
{
}

[Theory, CombinatorialData, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2531252")]
public async Task TestDocumentDiagnosticsReportsAdditionalFileDiagnostic(bool useVSDiagnostics, bool mutatingLspWorkspace)
{
var workspaceXml =
$"""
<Workspace>
<Project Language="C#" CommonReferences="true" AssemblyName="CSProj1" FilePath="C:\CSProj1.csproj">
<Document FilePath="C:\C.cs"></Document>
<AdditionalDocument FilePath="C:\Test.xaml"></AdditionalDocument>
</Project>
</Workspace>
""";

await using var testLspServer = await CreateTestWorkspaceFromXmlAsync(workspaceXml, mutatingLspWorkspace, BackgroundAnalysisScope.FullSolution, useVSDiagnostics);

var additionalDocument = testLspServer.GetCurrentSolution().Projects.Single().AdditionalDocuments.Single();
await testLspServer.OpenDocumentAsync(additionalDocument.GetURI());

var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, additionalDocument.GetURI(), useVSDiagnostics, category: TestAdditionalFileDocumentSourceProvider.DiagnosticSourceProviderName);
Assert.NotEmpty(results);
AssertEx.Equal(
[
@$"C:\Test.xaml: [{MockAdditionalFileDiagnosticAnalyzer.Id}]",
], results.Select(r => $"{r.Uri.GetRequiredParsedUri().LocalPath}: [{string.Join(", ", r.Diagnostics!.Select(d => d.Code?.Value?.ToString()))}]"));
}

[Theory, CombinatorialData]
public async Task TestWorkspaceDiagnosticsReportsAdditionalFileDiagnostic(bool useVSDiagnostics, bool mutatingLspWorkspace)
{
Expand Down Expand Up @@ -119,7 +151,7 @@ public async Task TestWorkspaceDiagnosticsWithAdditionalFileInMultipleProjects(b
AssertEx.Empty(results2);
}

protected override TestComposition Composition => base.Composition.AddParts(typeof(MockAdditionalFileDiagnosticAnalyzer));
protected override TestComposition Composition => base.Composition.AddParts(typeof(MockAdditionalFileDiagnosticAnalyzer), typeof(TestAdditionalFileDocumentSourceProvider));

private protected override TestAnalyzerReferenceByLanguage CreateTestAnalyzersReference()
=> new(ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>>.Empty.Add(LanguageNames.CSharp, [DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(LanguageNames.CSharp), new MockAdditionalFileDiagnosticAnalyzer()]));
Expand All @@ -128,10 +160,10 @@ private protected override TestAnalyzerReferenceByLanguage CreateTestAnalyzersRe
private sealed class MockAdditionalFileDiagnosticAnalyzer : DiagnosticAnalyzer
{
public const string Id = "MockAdditionalDiagnostic";
private readonly DiagnosticDescriptor _descriptor = new(Id, "MockAdditionalDiagnostic", "MockAdditionalDiagnostic", "InternalCategory", DiagnosticSeverity.Warning, isEnabledByDefault: true, helpLinkUri: "https://github.com/dotnet/roslyn");
internal static readonly DiagnosticDescriptor Descriptor = new(Id, "MockAdditionalDiagnostic", "MockAdditionalDiagnostic", "InternalCategory", DiagnosticSeverity.Warning, isEnabledByDefault: true, helpLinkUri: "https://github.com/dotnet/roslyn");

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> [_descriptor];
=> [Descriptor];

public override void Initialize(AnalysisContext context)
=> context.RegisterCompilationStartAction(CreateAnalyzerWithinCompilation);
Expand All @@ -140,7 +172,54 @@ public void CreateAnalyzerWithinCompilation(CompilationStartAnalysisContext cont
=> context.RegisterAdditionalFileAction(AnalyzeCompilation);

public void AnalyzeCompilation(AdditionalFileAnalysisContext context)
=> context.ReportDiagnostic(Diagnostic.Create(_descriptor,
=> context.ReportDiagnostic(Diagnostic.Create(Descriptor,
location: Location.Create(context.AdditionalFile.Path, Text.TextSpan.FromBounds(0, 0), new Text.LinePositionSpan(new Text.LinePosition(0, 0), new Text.LinePosition(0, 0))), "args"));
}

[Export(typeof(IDiagnosticSourceProvider)), Shared, PartNotDiscoverable]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class TestAdditionalFileDocumentSourceProvider() : IDiagnosticSourceProvider
{
internal const string DiagnosticSourceProviderName = "TestAdditionalFileSource";

bool IDiagnosticSourceProvider.IsDocument => true;

string IDiagnosticSourceProvider.Name => DiagnosticSourceProviderName;

bool IDiagnosticSourceProvider.IsEnabled(LSP.ClientCapabilities clientCapabilities) => true;

ValueTask<ImmutableArray<IDiagnosticSource>> IDiagnosticSourceProvider.CreateDiagnosticSourcesAsync(RequestContext context, CancellationToken cancellationToken)
{
if (context.TextDocument is not null && context.TextDocument is not Document)
{
return new([new TestAdditionalFileDocumentSource(context.TextDocument!)]);
}

return new([]);
}

private class TestAdditionalFileDocumentSource(TextDocument textDocument) : IDiagnosticSource
{
public Task<ImmutableArray<DiagnosticData>> GetDiagnosticsAsync(RequestContext context, CancellationToken cancellationToken)
{
var diagnostic = Diagnostic.Create(MockAdditionalFileDiagnosticAnalyzer.Descriptor,
location: Location.Create(context.TextDocument!.FilePath!, Text.TextSpan.FromBounds(0, 0), new Text.LinePositionSpan(new Text.LinePosition(0, 0), new Text.LinePosition(0, 0))), "args");
return Task.FromResult<ImmutableArray<DiagnosticData>>([DiagnosticData.Create(diagnostic, context.TextDocument.Project)]);
}

public LSP.TextDocumentIdentifier? GetDocumentIdentifier() => new LSP.TextDocumentIdentifier
{
DocumentUri = textDocument.GetURI()
};

public ProjectOrDocumentId GetId() => new(textDocument.Id);

public Project GetProject() => textDocument.Project;

public bool IsLiveSource() => true;

public string ToDisplayString() => textDocument.ToString()!;
}
}
}
5 changes: 3 additions & 2 deletions src/VisualStudio/CSharp/Impl/CSharpPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -52,6 +53,7 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService;
[ProvideLanguageEditorOptionPage(typeof(Options.NamingStylesOptionPage), "CSharp", @"Code Style", "Naming", pageNameResourceId: "#115", keywordListResourceId: 314)]
[ProvideLanguageEditorOptionPage(typeof(Options.IntelliSenseOptionPage), "CSharp", null, "IntelliSense", pageNameResourceId: "#103", keywordListResourceId: 312)]
[ProvideSettingsManifest(PackageRelativeManifestFile = @"UnifiedSettings\csharpSettings.registration.json")]
[ProvideService(typeof(ICSharpTempPECompilerService), IsAsyncQueryable = false, IsCacheable = true, IsFreeThreaded = true, ServiceName = "C# TempPE Compiler Service")]
[Guid(Guids.CSharpPackageIdString)]
internal sealed class CSharpPackage : AbstractPackage<CSharpPackage, CSharpLanguageService>, IVsUserSettingsQuery
{
Expand All @@ -69,10 +71,9 @@ private Task PackageInitializationBackgroundThreadAsync(PackageLoadTasks package
{
try
{
this.RegisterService<ICSharpTempPECompilerService>(async ct =>
((IServiceContainer)this).AddService(typeof(ICSharpTempPECompilerService), (_, _) =>
{
var workspace = this.ComponentModel.GetService<VisualStudioWorkspace>();
await JoinableTaskFactory.SwitchToMainThreadAsync(ct);
return new TempPECompilerService(workspace.Services.GetService<IMetadataService>());
});
}
Expand Down
5 changes: 0 additions & 5 deletions src/VisualStudio/CSharp/Impl/PackageRegistration.pkgdef
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@
"Name"="C# Language Service"
"IsAsyncQueryable"=dword:00000001

[$RootKey$\Services\{dba64c84-56df-4e20-8aa6-02332a97f474}]
@="{13c3bbb4-f18f-4111-9f54-a0fb010d9194}"
"Name"="C# TempPE Compiler Service"
"IsAsyncQueryable"=dword:00000001

[$RootKey$\AutomationProperties\TextEditor\CSharp-Specific]
@="#104"
"Description"="#105"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation
protected abstract IEnumerable<IVsEditorFactory> CreateEditorFactories();
protected abstract TLanguageService CreateLanguageService();

protected void RegisterService<T>(Func<CancellationToken, Task<T>> serviceCreator)
=> AddService(typeof(T), async (container, cancellationToken, type) => await serviceCreator(cancellationToken).ConfigureAwait(true), promote: true);

// When registering a language service, we need to take its ComAggregate wrapper.
protected void RegisterLanguageService(Type t, Func<CancellationToken, Task<object>> serviceCreator)
=> AddService(t, async (container, cancellationToken, type) => await serviceCreator(cancellationToken).ConfigureAwait(true), promote: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.

Imports System.ComponentModel.Design
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.ErrorReporting
Expand Down Expand Up @@ -37,6 +38,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
<ProvideLanguageEditorOptionPage(GetType(NamingStylesOptionPage), "Basic", "Code Style", "Naming", "#110", 10162)>
<ProvideLanguageEditorOptionPage(GetType(IntelliSenseOptionPage), "Basic", Nothing, "IntelliSense", "#112", 312)>
<ProvideSettingsManifest(PackageRelativeManifestFile:="UnifiedSettings\visualBasicSettings.registration.json")>
<ProvideService(GetType(IVbTempPECompilerFactory), IsAsyncQueryable:=False, IsCacheable:=True, IsFreeThreaded:=True, ServiceName:="Visual Basic TempPE Compiler Factory Service")>
<Guid(Guids.VisualBasicPackageIdString)>
Friend NotInheritable Class VisualBasicPackage
Inherits AbstractPackage(Of VisualBasicPackage, VisualBasicLanguageService)
Expand Down Expand Up @@ -73,12 +75,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
Try
RegisterLanguageService(GetType(IVbCompilerService), Function() Task.FromResult(_comAggregate))

RegisterService(Of IVbTempPECompilerFactory)(
Async Function(ct)
Dim workspace = Me.ComponentModel.GetService(Of VisualStudioWorkspace)()
Await JoinableTaskFactory.SwitchToMainThreadAsync(ct)
Return New TempPECompilerFactory(workspace)
End Function)
DirectCast(Me, IServiceContainer).AddService(
GetType(IVbTempPECompilerFactory),
Function(_1, _2) New TempPECompilerFactory(Me.ComponentModel.GetService(Of VisualStudioWorkspace)()))
Catch ex As Exception When FatalError.ReportAndPropagateUnlessCanceled(ex)
Throw ExceptionUtilities.Unreachable
End Try
Expand Down
Loading
Loading