|
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim;
using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.CPS;
using Microsoft.VisualStudio.LanguageServices.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework;
using Microsoft.VisualStudio.Shell.Interop;
using Xunit;
namespace Roslyn.VisualStudio.CSharp.UnitTests.ProjectSystemShim
{
internal static class CSharpHelpers
{
public static CSharpProjectShim CreateCSharpProject(TestEnvironment environment, string projectName)
{
var projectBinPath = Path.GetTempPath();
var hierarchy = environment.CreateHierarchy(projectName, projectBinPath, projectRefPath: null, projectCapabilities: "CSharp");
return CreateCSharpProject(environment, projectName, hierarchy);
}
public static CSharpProjectShim CreateCSharpProject(TestEnvironment environment, string projectName, IVsHierarchy hierarchy)
{
return new CSharpProjectShim(
new MockCSharpProjectRoot(hierarchy),
projectSystemName: projectName,
hierarchy: hierarchy,
serviceProvider: environment.ServiceProvider,
threadingContext: environment.ThreadingContext);
}
public static Task<CPSProject> CreateCSharpCPSProjectAsync(TestEnvironment environment, string projectName, params string[] commandLineArguments)
{
return CreateCSharpCPSProjectAsync(environment, projectName, projectGuid: Guid.NewGuid(), commandLineArguments: commandLineArguments);
}
public static Task<CPSProject> CreateCSharpCPSProjectAsync(TestEnvironment environment, string projectName, Guid projectGuid, params string[] commandLineArguments)
{
var projectFilePath = Path.GetTempPath();
var binOutputPath = GetOutputPathFromArguments(commandLineArguments) ?? Path.Combine(projectFilePath, projectName + ".dll");
return CreateCSharpCPSProjectAsync(environment, projectName, projectFilePath, binOutputPath, projectGuid, commandLineArguments);
}
public static Task<CPSProject> CreateCSharpCPSProjectAsync(TestEnvironment environment, string projectName, string binOutputPath, params string[] commandLineArguments)
{
var projectFilePath = Path.GetTempPath();
return CreateCSharpCPSProjectAsync(environment, projectName, projectFilePath, binOutputPath, projectGuid: Guid.NewGuid(), commandLineArguments: commandLineArguments);
}
public static unsafe void SetOption(this CSharpProjectShim csharpProject, CompilerOptions optionID, object value)
{
Assert.Equal(sizeof(HACK_VariantStructure), 8 + 2 * IntPtr.Size);
Assert.Equal(8, (int)Marshal.OffsetOf<HACK_VariantStructure>("_booleanValue"));
HACK_VariantStructure variant = default;
Marshal.GetNativeVariantForObject(value, (IntPtr)(&variant));
csharpProject.SetOption(optionID, variant);
}
public static async Task<CPSProject> CreateCSharpCPSProjectAsync(TestEnvironment environment, string projectName, string projectFilePath, string binOutputPath, Guid projectGuid, params string[] commandLineArguments)
{
var hierarchy = environment.CreateHierarchy(projectName, binOutputPath, projectRefPath: null, "CSharp");
var cpsProjectFactory = environment.ExportProvider.GetExportedValue<IWorkspaceProjectContextFactory>();
var data = new TestEvaluationData(projectFilePath, binOutputPath, assemblyName: "", binOutputPath, checksumAlgorithm: "SHA256");
var cpsProject = (CPSProject)await cpsProjectFactory.CreateProjectContextAsync(
projectGuid,
projectName,
LanguageNames.CSharp,
data,
hierarchy,
CancellationToken.None);
cpsProject.SetOptions(ImmutableArray.Create(commandLineArguments));
return cpsProject;
}
public static async Task<CPSProject> CreateNonCompilableProjectAsync(TestEnvironment environment, string projectName, string projectFilePath, string targetPath)
{
var hierarchy = environment.CreateHierarchy(projectName, projectBinPath: null, projectRefPath: null, projectCapabilities: "");
var cpsProjectFactory = environment.ExportProvider.GetExportedValue<IWorkspaceProjectContextFactory>();
var data = new TestEvaluationData(projectFilePath, targetPath, assemblyName: "", targetPath, checksumAlgorithm: "SHA256");
return (CPSProject)await cpsProjectFactory.CreateProjectContextAsync(
Guid.NewGuid(),
projectName,
NoCompilationConstants.LanguageName,
data,
hierarchy,
CancellationToken.None);
}
private static string GetOutputPathFromArguments(string[] commandLineArguments)
{
const string outPrefix = "/out:";
string outputPath = null;
foreach (var arg in commandLineArguments)
{
var index = arg.IndexOf(outPrefix);
if (index >= 0)
{
outputPath = arg[(index + outPrefix.Length)..];
}
}
return outputPath;
}
private sealed class TestCSharpCommandLineParserService : ICommandLineParserService
{
public CommandLineArguments Parse(IEnumerable<string> arguments, string baseDirectory, bool isInteractive, string sdkDirectory)
{
if (baseDirectory == null || !Directory.Exists(baseDirectory))
{
baseDirectory = Path.GetTempPath();
}
return CSharpCommandLineParser.Default.Parse(arguments, baseDirectory, sdkDirectory);
}
}
private class MockCSharpProjectRoot : ICSharpProjectRoot
{
private readonly IVsHierarchy _hierarchy;
public MockCSharpProjectRoot(IVsHierarchy hierarchy)
{
_hierarchy = hierarchy;
}
int ICSharpProjectRoot.BelongsToProject(string pszFileName)
{
throw new NotImplementedException();
}
string ICSharpProjectRoot.BuildPerConfigCacheFileName()
{
throw new NotImplementedException();
}
bool ICSharpProjectRoot.CanCreateFileCodeModel(string pszFile)
{
throw new NotImplementedException();
}
void ICSharpProjectRoot.ConfigureCompiler(ICSCompiler compiler, ICSInputSet inputSet, bool addSources)
{
throw new NotImplementedException();
}
object ICSharpProjectRoot.CreateFileCodeModel(string pszFile, ref Guid riid)
{
throw new NotImplementedException();
}
string ICSharpProjectRoot.GetActiveConfigurationName()
{
throw new NotImplementedException();
}
string ICSharpProjectRoot.GetFullProjectName()
{
throw new NotImplementedException();
}
int ICSharpProjectRoot.GetHierarchyAndItemID(string pszFile, out IVsHierarchy ppHier, out uint pItemID)
{
ppHier = _hierarchy;
// Each item should have it's own ItemID, but for simplicity we'll just hard-code a value of
// no particular significance.
pItemID = 42;
return VSConstants.S_OK;
}
void ICSharpProjectRoot.GetHierarchyAndItemIDOptionallyInProject(string pszFile, out IVsHierarchy ppHier, out uint pItemID, bool mustBeInProject)
{
throw new NotImplementedException();
}
string ICSharpProjectRoot.GetProjectLocation()
{
throw new NotImplementedException();
}
object ICSharpProjectRoot.GetProjectSite(ref Guid riid)
{
throw new NotImplementedException();
}
void ICSharpProjectRoot.SetProjectSite(ICSharpProjectSite site)
{
throw new NotImplementedException();
}
}
}
}
|