Files
SzmediTools/Szmedi.RvKits/ScriptPad/roslyn/ScriptingWorkspace.cs

138 lines
4.9 KiB
C#
Raw Normal View History

2025-09-16 16:06:41 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using System.IO;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
using System.Reflection;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
using Microsoft.CodeAnalysis.Host.Mef;
using System.Composition.Hosting;
namespace ScriptPad.Roslyn
{
internal class ScriptingWorkspace : Workspace
{
private ScriptingWorkspace(HostServices hostServices) : base(hostServices, WorkspaceKind.Interactive)
{
}
public Document GetDocument(DocumentId id)
{
return CurrentSolution.GetDocument(id);
}
public DocumentId AddProjectWithDocument(string documentFileName, string text)
{
var fileName = Path.GetFileName(documentFileName);
var name = Path.GetFileNameWithoutExtension(documentFileName);
var projectId = ProjectId.CreateNewId();
var references = ScriptGlobals.InitAssemblies.Distinct().Select(CreateReference).ToList();
var projectInfo = ProjectInfo.Create(
projectId,
VersionStamp.Default,
name,
name,
LanguageNames.CSharp,
isSubmission: true,
compilationOptions: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithScriptClassName(name),
metadataReferences: references,
parseOptions: new CSharpParseOptions(languageVersion: LanguageVersion.Latest));
OnProjectAdded(projectInfo);
var documentId = DocumentId.CreateNewId(projectId);
var documentInfo = DocumentInfo.Create(
documentId,
fileName,
sourceCodeKind: SourceCodeKind.Script,
loader: TextLoader.From(TextAndVersion.Create(SourceText.From(text, Encoding.UTF8), VersionStamp.Create())));
OnDocumentAdded(documentInfo);
return documentId;
}
public Project GetProject(DocumentId id)
{
return CurrentSolution.GetProject(id.ProjectId);
}
public void RemoveProject(DocumentId id)
{
OnProjectRemoved(id.ProjectId);
}
public void UpdateText(DocumentId documentId, string text)
{
OnDocumentTextChanged(documentId, SourceText.From(text, Encoding.UTF8), PreservationMode.PreserveValue);
}
public void UpdateText(DocumentId documentid, SourceText text)
{
OnDocumentTextChanged(documentid, text, PreservationMode.PreserveValue);
}
public Task<IReadOnlyList<Diagnostic>> GetDiagnosticsAsync(DocumentId documentId, CancellationToken cancellationToken)
{
return Task.Run(async () =>
{
var project = CurrentSolution.GetProject(documentId.ProjectId);
var compilation = await project.GetCompilationAsync(cancellationToken);
return (IReadOnlyList<Diagnostic>)compilation.GetDiagnostics(cancellationToken);
}, cancellationToken);
}
public override bool CanApplyChange(ApplyChangesKind feature)
{
return base.CanApplyChange(feature);
}
private MetadataReference CreateReference(Assembly assembly)
{
return MetadataReference.CreateFromFile(assembly.Location);
}
public void AddReference(string path, DocumentId id)
{
var references = GetReferences(id).OfType<PortableExecutableReference>();
if (references.Any(p => p.FilePath == path))
return;
PortableExecutableReference data = MetadataReference.CreateFromFile(path);
var pid = GetDocument(id).Project.Id;
OnMetadataReferenceAdded(pid, data);
}
public void RemoveReference(string path, DocumentId id)
{
var project = GetDocument(id).Project;
var data = project.MetadataReferences.FirstOrDefault(p => (p as PortableExecutableReference).FilePath == path);
OnMetadataReferenceRemoved(project.Id, data);
}
public IEnumerable<MetadataReference> GetReferences(DocumentId id)
{
var project = GetDocument(id).Project;
return project.MetadataReferences;
}
private static Lazy<ScriptingWorkspace> instance = new Lazy<ScriptingWorkspace>(() =>
{
var compositionHost = new ContainerConfiguration().WithAssemblies(MefHostServices.DefaultAssemblies).CreateContainer();
var hostService = MefHostServices.Create(compositionHost);
return new ScriptingWorkspace(hostService);
}, true);
public static ScriptingWorkspace GetInstance()
{
return instance.Value;
}
}
}