|
// Licensed to the .NET Foundation under one or more agreements.
// 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.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Legacy;
using Microsoft.VisualStudio.Shell.Interop;
namespace Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim
{
/// <summary>
/// The representation of a project to both the project factory and workspace API.
/// </summary>
/// <remarks>
/// Due to the number of interfaces this object must implement, all interface implementations
/// are in a separate files. Methods that are shared across multiple interfaces (which are
/// effectively methods that just QI from one interface to another), are implemented here.
/// </remarks>
internal sealed partial class CSharpProjectShim : AbstractLegacyProject, ICodeModelInstanceFactory
{
/// <summary>
/// This member is used to store a raw array of warning numbers, which is needed to properly implement
/// ICSCompilerConfig.GetWarnNumbers. Read the implementation of that function for more details.
/// </summary>
private readonly IntPtr _warningNumberArrayPointer;
private ICSharpProjectRoot _projectRoot;
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// Fetches the options processor for this C# project. Equivalent to the underlying member, but fixed to the derived type.
/// </summary>
private new OptionsProcessor ProjectSystemProjectOptionsProcessor
{
get => (OptionsProcessor)base.ProjectSystemProjectOptionsProcessor;
set => base.ProjectSystemProjectOptionsProcessor = value;
}
public CSharpProjectShim(
ICSharpProjectRoot projectRoot,
string projectSystemName,
IVsHierarchy hierarchy,
IServiceProvider serviceProvider,
IThreadingContext threadingContext)
: base(projectSystemName,
hierarchy,
LanguageNames.CSharp,
isVsIntellisenseProject: projectRoot is IVsIntellisenseProject,
serviceProvider,
threadingContext,
externalErrorReportingPrefix: "CS")
{
_projectRoot = projectRoot;
_serviceProvider = serviceProvider;
_warningNumberArrayPointer = Marshal.AllocHGlobal(0);
var componentModel = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
this.ProjectCodeModel = componentModel.GetService<IProjectCodeModelFactory>().CreateProjectCodeModel(ProjectSystemProject.Id, this);
this.ProjectSystemProjectOptionsProcessor = new OptionsProcessor(this.ProjectSystemProject, Workspace.Services.SolutionServices);
// Ensure the default options are set up
ResetAllOptions();
}
public override void Disconnect()
{
_projectRoot = null;
base.Disconnect();
}
~CSharpProjectShim()
{
// Free the unmanaged memory we allocated in the constructor
Marshal.FreeHGlobal(_warningNumberArrayPointer);
// Free any entry point strings.
if (_startupClasses != null)
{
foreach (var @class in _startupClasses)
{
Marshal.FreeHGlobal(@class);
}
}
}
EnvDTE.FileCodeModel ICodeModelInstanceFactory.TryCreateFileCodeModelThroughProjectSystem(string filePath)
{
if (_projectRoot.CanCreateFileCodeModel(filePath))
{
var iid = VSConstants.IID_IUnknown;
return _projectRoot.CreateFileCodeModel(filePath, ref iid) as EnvDTE.FileCodeModel;
}
else
{
return null;
}
}
}
}
|