|
// 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.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
{
public class TestHostProject
{
private readonly HostLanguageServices _languageServices;
private readonly ProjectId _id;
private readonly string _name;
private readonly IEnumerable<MetadataReference> _metadataReferences;
private readonly IEnumerable<AnalyzerReference> _analyzerReferences;
private readonly CompilationOptions _compilationOptions;
private readonly ParseOptions _parseOptions;
private readonly bool _isSubmission;
private readonly string _assemblyName;
private readonly Type _hostObjectType;
private readonly VersionStamp _version;
private readonly string _outputFilePath;
private readonly string _defaultNamespace;
public IEnumerable<TestHostDocument> Documents;
public IEnumerable<TestHostDocument> AdditionalDocuments;
public IEnumerable<TestHostDocument> AnalyzerConfigDocuments;
public IEnumerable<ProjectReference> ProjectReferences;
private string _filePath;
public string Name
{
get
{
return _name;
}
}
public IEnumerable<MetadataReference> MetadataReferences
{
get
{
return _metadataReferences;
}
}
public IEnumerable<AnalyzerReference> AnalyzerReferences
{
get
{
return _analyzerReferences;
}
}
public CompilationOptions CompilationOptions
{
get
{
return _compilationOptions;
}
}
public ParseOptions ParseOptions
{
get
{
return _parseOptions;
}
}
public ProjectId Id
{
get
{
return _id;
}
}
public bool IsSubmission
{
get
{
return _isSubmission;
}
}
public string AssemblyName
{
get
{
return _assemblyName;
}
}
public Type HostObjectType
{
get
{
return _hostObjectType;
}
}
public VersionStamp Version
{
get
{
return _version;
}
}
public string FilePath
{
get
{
return _filePath;
}
}
internal void OnProjectFilePathChanged(string filePath)
=> _filePath = filePath;
public string OutputFilePath
{
get { return _outputFilePath; }
}
public string DefaultNamespace
{
get { return _defaultNamespace; }
}
internal TestHostProject(
HostLanguageServices languageServices,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
params MetadataReference[] references)
: this(languageServices, compilationOptions, parseOptions, "Test", references)
{
}
internal TestHostProject(
HostLanguageServices languageServices,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
string assemblyName,
params MetadataReference[] references)
: this(languageServices,
compilationOptions,
parseOptions,
assemblyName: assemblyName,
projectName: assemblyName,
references: references,
documents: Array.Empty<TestHostDocument>())
{
}
internal TestHostProject(
HostLanguageServices languageServices,
CompilationOptions compilationOptions,
ParseOptions parseOptions,
string assemblyName,
string projectName,
IList<MetadataReference> references,
IList<TestHostDocument> documents,
IList<TestHostDocument> additionalDocuments = null,
IList<TestHostDocument> analyzerConfigDocuments = null,
Type hostObjectType = null,
bool isSubmission = false,
string filePath = null,
IList<AnalyzerReference> analyzerReferences = null,
string defaultNamespace = null)
{
_assemblyName = assemblyName;
_name = projectName;
_id = ProjectId.CreateNewId(debugName: this.AssemblyName);
_languageServices = languageServices;
_compilationOptions = compilationOptions;
_parseOptions = parseOptions;
_metadataReferences = references;
_analyzerReferences = analyzerReferences ?? SpecializedCollections.EmptyEnumerable<AnalyzerReference>();
this.Documents = documents;
this.AdditionalDocuments = additionalDocuments ?? SpecializedCollections.EmptyEnumerable<TestHostDocument>();
this.AnalyzerConfigDocuments = analyzerConfigDocuments ?? SpecializedCollections.EmptyEnumerable<TestHostDocument>();
ProjectReferences = SpecializedCollections.EmptyEnumerable<ProjectReference>();
_isSubmission = isSubmission;
_hostObjectType = hostObjectType;
_version = VersionStamp.Create();
_filePath = filePath;
_outputFilePath = GetTestOutputFilePath(filePath);
_defaultNamespace = defaultNamespace;
}
public TestHostProject(
TestWorkspace workspace,
TestHostDocument document,
string name = null,
string language = null,
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
IEnumerable<TestHostProject> projectReferences = null,
IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null,
string assemblyName = null,
string defaultNamespace = null)
: this(workspace, name, language, compilationOptions, parseOptions, SpecializedCollections.SingletonEnumerable(document), SpecializedCollections.EmptyEnumerable<TestHostDocument>(), SpecializedCollections.EmptyEnumerable<TestHostDocument>(), projectReferences, metadataReferences, analyzerReferences, assemblyName, defaultNamespace)
{
}
public TestHostProject(
TestWorkspace workspace,
string name = null,
string language = null,
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
IEnumerable<TestHostDocument> documents = null,
IEnumerable<TestHostDocument> additionalDocuments = null,
IEnumerable<TestHostDocument> analyzerConfigDocuments = null,
IEnumerable<TestHostProject> projectReferences = null,
IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null,
string assemblyName = null,
string defaultNamespace = null)
{
_name = name ?? "TestProject";
_id = ProjectId.CreateNewId(debugName: this.Name);
language = language ?? LanguageNames.CSharp;
_languageServices = workspace.Services.GetLanguageServices(language);
_compilationOptions = compilationOptions ?? this.LanguageServiceProvider.GetService<ICompilationFactoryService>().GetDefaultCompilationOptions();
_parseOptions = parseOptions ?? this.LanguageServiceProvider.GetService<ISyntaxTreeFactoryService>().GetDefaultParseOptions();
this.Documents = documents ?? SpecializedCollections.EmptyEnumerable<TestHostDocument>();
this.AdditionalDocuments = additionalDocuments ?? SpecializedCollections.EmptyEnumerable<TestHostDocument>();
this.AnalyzerConfigDocuments = analyzerConfigDocuments ?? SpecializedCollections.EmptyEnumerable<TestHostDocument>();
ProjectReferences = projectReferences != null ? projectReferences.Select(p => new ProjectReference(p.Id)) : SpecializedCollections.EmptyEnumerable<ProjectReference>();
_metadataReferences = metadataReferences ?? new MetadataReference[] { TestMetadata.Net451.mscorlib };
_analyzerReferences = analyzerReferences ?? SpecializedCollections.EmptyEnumerable<AnalyzerReference>();
_assemblyName = assemblyName ?? "TestProject";
_version = VersionStamp.Create();
_outputFilePath = GetTestOutputFilePath(_filePath);
_defaultNamespace = defaultNamespace;
if (documents != null)
{
foreach (var doc in documents)
{
doc.SetProject(this);
}
}
if (additionalDocuments != null)
{
foreach (var doc in additionalDocuments)
{
doc.SetProject(this);
}
}
if (analyzerConfigDocuments != null)
{
foreach (var doc in analyzerConfigDocuments)
{
doc.SetProject(this);
}
}
}
internal void SetSolution(TestHostSolution _)
{
// set up back pointer to this project.
if (this.Documents != null)
{
foreach (var doc in this.Documents)
{
doc.SetProject(this);
}
foreach (var doc in this.AdditionalDocuments)
{
doc.SetProject(this);
}
foreach (var doc in this.AnalyzerConfigDocuments)
{
doc.SetProject(this);
}
}
}
internal void AddDocument(TestHostDocument document)
{
this.Documents = this.Documents.Concat(new TestHostDocument[] { document });
document.SetProject(this);
}
internal void RemoveDocument(TestHostDocument document)
=> this.Documents = this.Documents.Where(d => d != document);
internal void AddAdditionalDocument(TestHostDocument document)
{
this.AdditionalDocuments = this.AdditionalDocuments.Concat(new TestHostDocument[] { document });
document.SetProject(this);
}
internal void RemoveAdditionalDocument(TestHostDocument document)
=> this.AdditionalDocuments = this.AdditionalDocuments.Where(d => d != document);
internal void AddAnalyzerConfigDocument(TestHostDocument document)
{
this.AnalyzerConfigDocuments = this.AnalyzerConfigDocuments.Concat(new TestHostDocument[] { document });
document.SetProject(this);
}
internal void RemoveAnalyzerConfigDocument(TestHostDocument document)
=> this.AnalyzerConfigDocuments = this.AnalyzerConfigDocuments.Where(d => d != document);
public string Language
{
get
{
return _languageServices.Language;
}
}
internal HostLanguageServices LanguageServiceProvider
{
get
{
return _languageServices;
}
}
public ProjectInfo ToProjectInfo()
{
return ProjectInfo.Create(
new ProjectInfo.ProjectAttributes(
Id,
Version,
name: Name,
assemblyName: AssemblyName,
language: Language,
compilationOutputFilePaths: default,
checksumAlgorithm: Text.SourceHashAlgorithms.Default,
defaultNamespace: DefaultNamespace,
filePath: FilePath,
outputFilePath: OutputFilePath,
isSubmission: IsSubmission),
CompilationOptions,
ParseOptions,
documents: Documents.Where(d => !d.IsSourceGenerated).Select(d => d.ToDocumentInfo()),
ProjectReferences,
MetadataReferences,
AnalyzerReferences,
additionalDocuments: AdditionalDocuments.Select(d => d.ToDocumentInfo()),
analyzerConfigDocuments: AnalyzerConfigDocuments.Select(d => d.ToDocumentInfo()),
HostObjectType);
}
// It is identical with the internal extension method 'GetDefaultExtension' defined in OutputKind.cs.
// However, we could not apply for InternalVisibleToTest due to other parts of this assembly
// complaining about CS0507: "cannot change access modifiers when overriding 'access' inherited member".
private static string GetDefaultExtension(OutputKind kind)
{
switch (kind)
{
case OutputKind.ConsoleApplication:
case OutputKind.WindowsApplication:
case OutputKind.WindowsRuntimeApplication:
return ".exe";
case OutputKind.DynamicallyLinkedLibrary:
return ".dll";
case OutputKind.NetModule:
return ".netmodule";
case OutputKind.WindowsRuntimeMetadata:
return ".winmdobj";
default:
return ".dll";
}
}
private string GetTestOutputFilePath(string filepath)
{
var outputFilePath = @"Z:\";
try
{
outputFilePath = Path.GetDirectoryName(filepath);
}
catch (ArgumentException)
{
}
if (string.IsNullOrEmpty(outputFilePath))
{
outputFilePath = @"Z:\";
}
return this.CompilationOptions == null ? "" : Path.Combine(outputFilePath, this.AssemblyName + GetDefaultExtension(this.CompilationOptions.OutputKind));
}
}
}
|