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
22 changes: 10 additions & 12 deletions src/VisualStudio/CSharp/Impl/CSharpPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -57,7 +55,7 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
[Guid(Guids.CSharpPackageIdString)]
internal sealed class CSharpPackage : AbstractPackage<CSharpPackage, CSharpLanguageService>, IVsUserSettingsQuery
{
private ObjectBrowserLibraryManager _libraryManager;
private ObjectBrowserLibraryManager? _libraryManager;
private uint _libraryManagerCookie;

protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
Expand All @@ -79,13 +77,13 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
}
}

protected override async Task RegisterObjectBrowserLibraryManagerAsync(CancellationToken cancellationToken)
protected override void RegisterObjectBrowserLibraryManager()
{
var workspace = this.ComponentModel.GetService<VisualStudioWorkspace>();
Contract.ThrowIfFalse(JoinableTaskFactory.Context.IsOnMainThread);

await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
var workspace = this.ComponentModel.GetService<VisualStudioWorkspace>();

if (await GetServiceAsync(typeof(SVsObjectManager)).ConfigureAwait(true) is IVsObjectManager2 objectManager)
if (GetService(typeof(SVsObjectManager)) is IVsObjectManager2 objectManager)
{
_libraryManager = new ObjectBrowserLibraryManager(this, ComponentModel, workspace);

Expand All @@ -96,19 +94,19 @@ protected override async Task RegisterObjectBrowserLibraryManagerAsync(Cancellat
}
}

protected override async Task UnregisterObjectBrowserLibraryManagerAsync(CancellationToken cancellationToken)
protected override void UnregisterObjectBrowserLibraryManager()
{
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
Contract.ThrowIfFalse(JoinableTaskFactory.Context.IsOnMainThread);

if (_libraryManagerCookie != 0)
{
if (await GetServiceAsync(typeof(SVsObjectManager)).ConfigureAwait(true) is IVsObjectManager2 objectManager)
if (GetService(typeof(SVsObjectManager)) is IVsObjectManager2 objectManager)
{
objectManager.UnregisterLibrary(_libraryManagerCookie);
_libraryManagerCookie = 0;
}

_libraryManager.Dispose();
_libraryManager?.Dispose();
_libraryManager = null;
}
}
Expand Down Expand Up @@ -136,7 +134,7 @@ protected override IEnumerable<IVsEditorFactory> CreateEditorFactories()
var editorFactory = new CSharpEditorFactory(this.ComponentModel);
var codePageEditorFactory = new CSharpCodePageEditorFactory(editorFactory);

return new IVsEditorFactory[] { editorFactory, codePageEditorFactory };
return [editorFactory, codePageEditorFactory];
}

protected override CSharpLanguageService CreateLanguageService()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System.Runtime.InteropServices;
using Microsoft.VisualStudio.LanguageServices.Implementation;

namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
{
[Guid(Guids.CSharpCodePageEditorFactoryIdString)]
internal class CSharpCodePageEditorFactory : AbstractCodePageEditorFactory
internal sealed class CSharpCodePageEditorFactory(AbstractEditorFactory editorFactory) : AbstractCodePageEditorFactory(editorFactory)
{
public CSharpCodePageEditorFactory(AbstractEditorFactory editorFactory)
: base(editorFactory)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
Expand All @@ -18,13 +16,8 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
{
[ExcludeFromCodeCoverage]
[Guid(Guids.CSharpEditorFactoryIdString)]
internal class CSharpEditorFactory : AbstractEditorFactory
internal class CSharpEditorFactory(IComponentModel componentModel) : AbstractEditorFactory(componentModel)
{
public CSharpEditorFactory(IComponentModel componentModel)
: base(componentModel)
{
}

protected override string ContentTypeName => ContentTypeNames.CSharpContentType;
protected override string LanguageName => LanguageNames.CSharp;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
Expand All @@ -25,22 +24,18 @@
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.WinForms.Interfaces;
using Roslyn.Utilities;

namespace Microsoft.VisualStudio.LanguageServices.Implementation;

/// <summary>
/// The base class of both the Roslyn editor factories.
/// </summary>
internal abstract class AbstractEditorFactory : IVsEditorFactory, IVsEditorFactory4, IVsEditorFactoryNotify
internal abstract class AbstractEditorFactory(IComponentModel componentModel) : IVsEditorFactory, IVsEditorFactory4, IVsEditorFactoryNotify
{
private readonly IComponentModel _componentModel;
private readonly IComponentModel _componentModel = componentModel;
private Microsoft.VisualStudio.OLE.Interop.IServiceProvider? _oleServiceProvider;
private bool _encoding;

protected AbstractEditorFactory(IComponentModel componentModel)
=> _componentModel = componentModel;

protected abstract string ContentTypeName { get; }
protected abstract string LanguageName { get; }

Expand Down
36 changes: 19 additions & 17 deletions src/VisualStudio/Core/Def/LanguageService/AbstractPackage`2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +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.

#nullable disable

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.SymbolSearch;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
Expand All @@ -25,10 +24,11 @@ internal abstract partial class AbstractPackage<TPackage, TLanguageService> : Ab
where TPackage : AbstractPackage<TPackage, TLanguageService>
where TLanguageService : AbstractLanguageService<TPackage, TLanguageService>
{
private TLanguageService _languageService;
private TLanguageService? _languageService;

private PackageInstallerService _packageInstallerService;
private VisualStudioSymbolSearchService _symbolSearchService;
private PackageInstallerService? _packageInstallerService;
private VisualStudioSymbolSearchService? _symbolSearchService;
private IVsShell? _shell;

protected AbstractPackage()
{
Expand All @@ -40,12 +40,14 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke

await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

var shell = (IVsShell7)await GetServiceAsync(typeof(SVsShell)).ConfigureAwait(true);
var solution = (IVsSolution)await GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(true);
cancellationToken.ThrowIfCancellationRequested();
var shell = (IVsShell7?)await GetServiceAsync(typeof(SVsShell)).ConfigureAwait(true);
var solution = (IVsSolution?)await GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(true);
Assumes.Present(shell);
Assumes.Present(solution);

_shell = (IVsShell?)shell;
Assumes.Present(_shell);

foreach (var editorFactory in CreateEditorFactories())
{
RegisterEditorFactory(editorFactory);
Expand All @@ -61,19 +63,19 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
_languageService = CreateLanguageService();
await _languageService.SetupAsync(cancellationToken).ConfigureAwait(false);

return _languageService.ComAggregate;
return _languageService.ComAggregate!;
});

await shell.LoadPackageAsync(Guids.RoslynPackageId);

var miscellaneousFilesWorkspace = this.ComponentModel.GetService<MiscellaneousFilesWorkspace>();
RegisterMiscellaneousFilesWorkspaceInformation(miscellaneousFilesWorkspace);

if (!IVsShellExtensions.IsInCommandLineMode(JoinableTaskFactory))
if (!_shell.IsInCommandLineMode())
{
// not every derived package support object browser and for those languages
// this is a no op
await RegisterObjectBrowserLibraryManagerAsync(cancellationToken).ConfigureAwait(true);
RegisterObjectBrowserLibraryManager();
}

LoadComponentsInUIContextOnceSolutionFullyLoadedAsync(cancellationToken).Forget();
Expand Down Expand Up @@ -117,9 +119,11 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!IVsShellExtensions.IsInCommandLineMode(JoinableTaskFactory))
// Per VS core team, Package.Dispose is called on the UI thread.
Contract.ThrowIfFalse(JoinableTaskFactory.Context.IsOnMainThread);
if (_shell != null && !_shell.IsInCommandLineMode())
{
JoinableTaskFactory.Run(async () => await UnregisterObjectBrowserLibraryManagerAsync(CancellationToken.None).ConfigureAwait(true));
UnregisterObjectBrowserLibraryManager();
}

// If we've created the language service then tell it it's time to clean itself up now.
Expand All @@ -135,17 +139,15 @@ protected override void Dispose(bool disposing)

protected abstract string RoslynLanguageName { get; }

protected virtual Task RegisterObjectBrowserLibraryManagerAsync(CancellationToken cancellationToken)
protected virtual void RegisterObjectBrowserLibraryManager()
{
// it is virtual rather than abstract to not break other languages which derived from our
// base package implementations
return Task.CompletedTask;
}

protected virtual Task UnregisterObjectBrowserLibraryManagerAsync(CancellationToken cancellationToken)
protected virtual void UnregisterObjectBrowserLibraryManager()
{
// it is virtual rather than abstract to not break other languages which derived from our
// base package implementations
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
Expand Down Expand Up @@ -48,11 +46,11 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IOpenText
/// The mapping of all monikers in the RDT and the <see cref="ProjectId"/> of the project and <see cref="SourceTextContainer"/> of the open
/// file we have created for that open buffer. An entry should only be in here if it's also already in <see cref="_monikerToWorkspaceRegistration"/>.
/// </summary>
private readonly Dictionary<string, (ProjectId projectId, SourceTextContainer textContainer)> _monikersToProjectIdAndContainer = new Dictionary<string, (ProjectId, SourceTextContainer)>();
private readonly Dictionary<string, (ProjectId projectId, SourceTextContainer textContainer)> _monikersToProjectIdAndContainer = [];

private readonly ImmutableArray<MetadataReference> _metadataReferences;

private IVsTextManager _textManager;
private IVsTextManager? _textManager;

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
Expand Down Expand Up @@ -80,7 +78,7 @@ public async Task InitializeAsync()
_textManager = await _textManagerService.GetValueAsync().ConfigureAwait(false);
}

void IOpenTextBufferEventListener.OnOpenDocument(string moniker, ITextBuffer textBuffer, IVsHierarchy _) => TrackOpenedDocument(moniker, textBuffer);
void IOpenTextBufferEventListener.OnOpenDocument(string moniker, ITextBuffer textBuffer, IVsHierarchy? _) => TrackOpenedDocument(moniker, textBuffer);

void IOpenTextBufferEventListener.OnCloseDocument(string moniker) => TryUntrackClosingDocument(moniker);

Expand Down Expand Up @@ -116,11 +114,11 @@ void IOpenTextBufferEventListener.OnSaveDocument(string moniker) { }
public void RegisterLanguage(Guid languageGuid, string languageName, string scriptExtension)
=> _languageInformationByLanguageGuid.Add(languageGuid, new LanguageInformation(languageName, scriptExtension));

private LanguageInformation TryGetLanguageInformation(string filename)
private LanguageInformation? TryGetLanguageInformation(string filename)
{
LanguageInformation languageInformation = null;
LanguageInformation? languageInformation = null;

if (ErrorHandler.Succeeded(_textManager.MapFilenameToLanguageSID(filename, out var fileLanguageGuid)))
if (_textManager != null && ErrorHandler.Succeeded(_textManager.MapFilenameToLanguageSID(filename, out var fileLanguageGuid)))
{
_languageInformationByLanguageGuid.TryGetValue(fileLanguageGuid, out languageInformation);
}
Expand All @@ -133,6 +131,9 @@ private IEnumerable<MetadataReference> CreateMetadataReferences()
var manager = this.Services.GetService<VisualStudioMetadataReferenceManager>();
var searchPaths = VisualStudioMetadataReferenceManager.GetReferencePaths();

if (manager == null)
return [];

return from fileName in new[] { "mscorlib.dll", "System.dll", "System.Core.dll" }
let fullPath = FileUtilities.ResolveRelativePath(fileName, basePath: null, baseDirectory: null, searchPaths: searchPaths, fileExists: File.Exists)
where fullPath != null
Expand Down
10 changes: 5 additions & 5 deletions src/VisualStudio/Core/Def/RoslynPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ internal sealed class RoslynPackage : AbstractPackage
private const string BackgroundAnalysisScopeOptionKey = "AnalysisScope-DCE33A29A768";
private const byte BackgroundAnalysisScopeOptionVersion = 1;

private static RoslynPackage? _lazyInstance;
private static RoslynPackage? s_lazyInstance;

private RuleSetEventHandler? _ruleSetEventHandler;
private ColorSchemeApplier? _colorSchemeApplier;
private IDisposable? _solutionEventMonitor;
private SolutionEventMonitor? _solutionEventMonitor;

private BackgroundAnalysisScope? _analysisScope;

Expand Down Expand Up @@ -95,7 +95,7 @@ public BackgroundAnalysisScope? AnalysisScope

internal static async ValueTask<RoslynPackage?> GetOrLoadAsync(IThreadingContext threadingContext, IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken)
{
if (_lazyInstance is null)
if (s_lazyInstance is null)
{
await threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

Expand All @@ -105,11 +105,11 @@ public BackgroundAnalysisScope? AnalysisScope

if (ErrorHandler.Succeeded(((IVsShell)shell).IsPackageLoaded(typeof(RoslynPackage).GUID, out var package)))
{
_lazyInstance = (RoslynPackage)package;
s_lazyInstance = (RoslynPackage)package;
}
}

return _lazyInstance;
return s_lazyInstance;
}

protected override void OnLoadOptions(string key, Stream stream)
Expand Down
27 changes: 7 additions & 20 deletions src/VisualStudio/Core/Def/Utilities/IVsShellExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Threading;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.Utilities;

Expand All @@ -19,30 +15,21 @@ internal static class IVsShellExtensions
/// <summary>
/// Returns true if devenv is invoked in command line mode for build, e.g. devenv /rebuild MySolution.sln
/// </summary>
public static bool IsInCommandLineMode(JoinableTaskFactory joinableTaskFactory)
public static bool IsInCommandLineMode(this IVsShell shell)
{
var result = s_isInCommandLineMode;
if (result == 0)
if (s_isInCommandLineMode == 0)
{
s_isInCommandLineMode = result = joinableTaskFactory.Run(async () =>
{
await joinableTaskFactory.SwitchToMainThreadAsync();

var shell = ServiceProvider.GlobalProvider.GetService<SVsShell, IVsShell>(joinableTaskFactory);
return
(shell != null) &&
ErrorHandler.Succeeded(shell.GetProperty((int)__VSSPROPID.VSSPROPID_IsInCommandLineMode, out var result)) &&
(bool)result ? 1 : -1;
});
s_isInCommandLineMode =
ErrorHandler.Succeeded(shell.GetProperty((int)__VSSPROPID.VSSPROPID_IsInCommandLineMode, out var result)) &&
(bool)result ? 1 : -1;
}

return result == 1;
return s_isInCommandLineMode == 1;
}

public static bool TryGetPropertyValue(this IVsShell shell, __VSSPROPID id, out IntPtr value)
{
var hresult = shell.GetProperty((int)id, out var objValue);
if (ErrorHandler.Succeeded(hresult) && objValue != null)
if (ErrorHandler.Succeeded(shell.GetProperty((int)id, out var objValue)) && objValue != null)
{
value = (IntPtr.Size == 4) ? (IntPtr)(int)objValue : (IntPtr)(long)objValue;
return true;
Expand Down
Loading
Loading