private async Task <Solution> GetSolutionAsync(ISolutionChecksumService service, ChecksumScope snapshot) { var workspace = new AdhocWorkspace(); var solutionInfo = await GetValueAsync <SolutionChecksumObjectInfo>(service, snapshot.SolutionChecksum.Info, WellKnownChecksumObjects.SolutionChecksumObjectInfo).ConfigureAwait(false); var projects = new List <ProjectInfo>(); foreach (var projectSnapshot in snapshot.SolutionChecksum.Projects.ToProjectObjects(service)) { var documents = new List <DocumentInfo>(); foreach (var documentSnapshot in projectSnapshot.Documents.ToDocumentObjects(service)) { var documentInfo = await GetValueAsync <DocumentChecksumObjectInfo>(service, documentSnapshot.Info, WellKnownChecksumObjects.DocumentChecksumObjectInfo).ConfigureAwait(false); var text = await GetValueAsync <SourceText>(service, documentSnapshot.Text, WellKnownChecksumObjects.SourceText).ConfigureAwait(false); // TODO: do we need version? documents.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())), documentInfo.FilePath, documentInfo.IsGenerated)); } var p2p = new List <ProjectReference>(); foreach (var checksum in projectSnapshot.ProjectReferences) { var reference = await GetValueAsync <ProjectReference>(service, checksum, WellKnownChecksumObjects.ProjectReference).ConfigureAwait(false); p2p.Add(reference); } var metadata = new List <MetadataReference>(); foreach (var checksum in projectSnapshot.MetadataReferences) { var reference = await GetValueAsync <MetadataReference>(service, checksum, WellKnownChecksumObjects.MetadataReference).ConfigureAwait(false); metadata.Add(reference); } var analyzers = new List <AnalyzerReference>(); foreach (var checksum in projectSnapshot.AnalyzerReferences) { var reference = await GetValueAsync <AnalyzerReference>(service, checksum, WellKnownChecksumObjects.AnalyzerReference).ConfigureAwait(false); analyzers.Add(reference); } var additionals = new List <DocumentInfo>(); foreach (var documentSnapshot in projectSnapshot.AdditionalDocuments.ToDocumentObjects(service)) { var documentInfo = await GetValueAsync <DocumentChecksumObjectInfo>(service, documentSnapshot.Info, WellKnownChecksumObjects.DocumentChecksumObjectInfo).ConfigureAwait(false); var text = await GetValueAsync <SourceText>(service, documentSnapshot.Text, WellKnownChecksumObjects.SourceText).ConfigureAwait(false); // TODO: do we need version? additionals.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())), documentInfo.FilePath, documentInfo.IsGenerated)); } var projectInfo = await GetValueAsync <ProjectChecksumObjectInfo>(service, projectSnapshot.Info, WellKnownChecksumObjects.ProjectChecksumObjectInfo).ConfigureAwait(false); var compilationOptions = await GetValueAsync <CompilationOptions>(service, projectSnapshot.CompilationOptions, WellKnownChecksumObjects.CompilationOptions).ConfigureAwait(false); var parseOptions = await GetValueAsync <ParseOptions>(service, projectSnapshot.ParseOptions, WellKnownChecksumObjects.ParseOptions).ConfigureAwait(false); projects.Add( ProjectInfo.Create( projectInfo.Id, projectInfo.Version, projectInfo.Name, projectInfo.AssemblyName, projectInfo.Language, projectInfo.FilePath, projectInfo.OutputFilePath, compilationOptions, parseOptions, documents, p2p, metadata, analyzers, additionals)); } return(workspace.AddSolution(SolutionInfo.Create(solutionInfo.Id, solutionInfo.Version, solutionInfo.FilePath, projects))); }
private async Task SetupCodeControlAsync() { var w = new AdhocWorkspace(Host); #if false foreach (var fieldInfo in w.GetType().GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic)) { var v = fieldInfo.GetValue(w); Debug.WriteLine($"{fieldInfo.Name}: {v}"); } var langSvc = w.Services.GetLanguageServices(LanguageNames.CSharp); var method = langSvc.GetType().GetMethod("GetService", BindingFlags.Instance | BindingFlags.Public); List <object> services = new List <object>(); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { foreach (var type in assembly.GetTypes()) { if (typeof(ILanguageService).IsAssignableFrom(type)) { try { if (!type.ContainsGenericParameters) { var m = method.MakeGenericMethod(new[] { type }); var result = m.Invoke(langSvc, new object[] { }); if (result != null) { Debug.WriteLine(result); services.Add(result); } } } catch { } if (type.IsPublic) { Debug.WriteLine(String.Format("{0:G5}", type.IsPublic.ToString()) + " " + type.FullName); } } } } catch { } } foreach (object service in services) { foreach (var methodInfo in service.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { Debug.WriteLine((methodInfo.ReturnType?.FullName ?? "") + " " + service.GetType().FullName + "." + methodInfo.Name + "( " + string.Join(", ", methodInfo.GetParameters().Select(p => (p.IsOptional ? " optional " : "") + p.ParameterType + " " + p.Name)) + ")"); } if (service.GetType().Name == "CSharpCodeCleanupService") { } } // w.Services.FindLanguageServices<IFormattingService>(metadata => // { // foreach (var (key, value) in metadata) // { // Debug.WriteLine($"{key} = {value}"); // } // Debug.WriteLine(""); // return false; // }); #endif w.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Code Project", "code", LanguageNames.CSharp); var w2 = w.CurrentSolution.AddProject(projectInfo); w.TryApplyChanges(w2); DocumentInfo documentInfo; var filename = Filename; if (filename != null) { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular, new FileTextLoader(filename, Encoding.UTF8), filename); } else { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular); } w2 = w.CurrentSolution.AddDocument(documentInfo); w.TryApplyChanges(w2); Project1 = w.CurrentSolution.GetProject(projectInfo.Id); Document1 = w.CurrentSolution.GetDocument(documentInfo.Id); var qui = w.Services.GetLanguageServices(LanguageNames.CSharp).GetService <QuickInfoService>(); var textAsync = await Document1.GetTextAsync(); if (false) { for (var i = 0; i < textAsync.Length; i++) { var re = await qui.GetQuickInfoAsync(Document1, i); if (re != null) { Debug.WriteLine(re.Span.ToString()); Debug.WriteLine("tags = " + string.Join(";", re.Tags)); foreach (var reRelatedSpan in re.RelatedSpans) { Debug.WriteLine("relatedspan " + reRelatedSpan.ToString()); } foreach (var quickInfoSection in re.Sections) { Debug.WriteLine("" + i + " Text(" + quickInfoSection.Text + ") Kind(" + quickInfoSection.Kind + ") TaggedParts(" + String.Join(", ", quickInfoSection.TaggedParts) + ")"); } } } } CodeControl.DebugLevel = 2; CodeControl.JTF2 = JTF2; CodeControl.Document = Document1; var tree = await Document1.GetSyntaxTreeAsync(); CodeControl.SyntaxTree = tree; var model = await Document1.GetSemanticModelAsync(); CodeControl.SemanticModel = model; CodeControl.Compilation = model.Compilation; // CodeControl.AddHandler(RoslynCodeControl.ContentChangedEvent, new RoslynCodeControl.ContentChangedRoutedEventHandler(CodeControlContentChanged)); CodeControl.AddHandler(RoslynCodeBase.RenderStartEvent, new RoutedEventHandler((sender, args) => { // StartTime = DateTime.Now; Debug.WriteLine("render start"); })); CodeControl.AddHandler(RoslynCodeBase.RenderCompleteEvent, new RoutedEventHandler((sender, args) => { // var span = DateTime.Now - StartTime; Debug.WriteLine("render complete "); })); await CodeControl.UpdateFormattedTextAsync(); }
/// <summary> /// Starts pushing events from the given projects to the workspace hosts and notifies about open documents. /// </summary> /// <remarks>This method must be called on the foreground thread.</remarks> internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments(IEnumerable <AbstractProject> projects) { AssertIsForeground(); // If the solution is closing we shouldn't do anything, because all of our state is // in the process of going away. This can happen if we receive notification that a document has // opened in the middle of the solution close operation. if (_solutionIsClosing) { return; } // We need to push these projects and any project dependencies we already know about. Therefore, compute the // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order. var visited = new HashSet <AbstractProject>(); var inOrderToPush = new List <AbstractProject>(); void addToInOrderToPush(AbstractProject project) { Contract.ThrowIfFalse(ContainsProject(project)); // Bail out if any of the following is true: // 1. We have already started pushing changes for this project OR // 2. We have already visited this project in a prior recursive call if (_pushedProjects.Contains(project) || !visited.Add(project)) { return; } foreach (var projectReference in project.GetCurrentProjectReferences()) { addToInOrderToPush(GetProject(projectReference.ProjectId)); } inOrderToPush.Add(project); } foreach (var project in projects) { addToInOrderToPush(project); } var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray(); // We need to enable projects to start pushing changes to the workspace even before we add the solution/project to the host. // This is required because between the point we capture the project info for current state and the point where we start pushing to the workspace, // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject. // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks. foreach (var project in inOrderToPush) { project.PushingChangesToWorkspace = true; Logger.Log(FunctionId.AbstractProject_PushedToWorkspace, KeyValueLogMessage.Create(LogType.Trace, m => { m[AbstractProject.ProjectGuidPropertyName] = project.Guid; })); } using (WorkspaceServices.GetService <IGlobalOperationNotificationService>()?.Start("Add Project to Workspace")) { if (!_solutionAdded) { string solutionFilePath = null; VersionStamp?version = default; // Figure out the solution version if (ErrorHandler.Succeeded(_vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null) { solutionFilePath = Path.Combine(solutionDirectory, solutionFileName); if (File.Exists(solutionFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath)); } } if (version == null) { version = VersionStamp.Create(); } var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName); var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos); NotifyWorkspace(workspace => workspace.OnSolutionAdded(solutionInfo)); _solutionAdded = true; var persistenceService = WorkspaceServices.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService; persistenceService?.UpdateForVisualStudioWorkspace(_workspace); } else { // The solution is already added, so we'll just do project added notifications from here foreach (var projectInfo in projectInfos) { NotifyWorkspace(workspace => workspace.OnProjectAdded(projectInfo)); } } foreach (var project in inOrderToPush) { _pushedProjects.Add(project); foreach (var document in project.GetCurrentDocuments()) { if (document.IsOpen) { NotifyWorkspace(workspace => { workspace.OnDocumentOpened( document.Id, document.GetOpenTextBuffer().AsTextContainer(), isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _runningDocumentTable)); (workspace as VisualStudioWorkspaceImpl)?.ConnectToSharedHierarchyEvents(document); }); } } } } }
public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo) { // HACK: Fetch this service to ensure it's still created on the UI thread; once this is moved off we'll need to fix up it's constructor to be free-threaded. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); // HACK: since we're on the UI thread, ensure we initialize our options provider which depends on a UI-affinitized experimentation service _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitialized(); var id = ProjectId.CreateNewId(projectSystemName); var directoryNameOpt = creationInfo.FilePath != null?Path.GetDirectoryName(creationInfo.FilePath) : null; // We will use the project system name as the default display name of the project var project = new VisualStudioProject(_visualStudioWorkspaceImpl, _dynamicFileInfoProviders, _hostDiagnosticUpdateSource, id, displayName: projectSystemName, language, directoryNameOpt); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); var assemblyName = creationInfo.AssemblyName ?? projectSystemName; _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectSystemName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions); // If we don't have any projects and this is our first project being added, then we'll create a new SolutionId if (w.CurrentSolution.ProjectIds.Count == 0) { // Fetch the current solution path. Since we're on the UI thread right now, we can do that. string solutionFilePath = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null) { if (ErrorHandler.Failed(solution.GetSolutionInfo(out _, out solutionFilePath, out _))) { // Paranoia: if the call failed, we definitely don't want to use any stuff that was set solutionFilePath = null; } } w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionFilePath), VersionStamp.Create(), solutionFilePath, projects: new[] { projectInfo })); // set working folder for the persistent service var persistenceService = w.Services.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService; persistenceService?.UpdateForVisualStudioWorkspace(w); } else { w.OnProjectAdded(projectInfo); } }); // We do all these sets after the w.OnProjectAdded, as the setting of these properties is going to try to modify the workspace // again. Those modifications will all implicitly do nothing, since the workspace already has the values from above. // We could pass these all through the constructor (but that gets verbose), or have some other control to ignore these, // but that seems like overkill. project.AssemblyName = assemblyName; project.CompilationOptions = creationInfo.CompilationOptions; project.FilePath = creationInfo.FilePath; project.ParseOptions = creationInfo.ParseOptions; return(project); }
private Task <SolutionInfo> LoadSolutionInfo(ProjectInfo projectInfo) { return(Task.FromResult(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create(), projects: new[] { projectInfo }))); }
public VisualStudioProject CreateAndAddToWorkspace(string projectUniqueName, string language, VisualStudioProjectCreationInfo creationInfo) { // HACK: Fetch this service to ensure it's still created on the UI thread; once this is moved off we'll need to fix up it's constructor to be free-threaded. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); var id = ProjectId.CreateNewId(projectUniqueName); var directoryNameOpt = creationInfo.FilePath != null?Path.GetDirectoryName(creationInfo.FilePath) : null; var project = new VisualStudioProject(_visualStudioWorkspaceImpl, _hostDiagnosticUpdateSource, id, projectUniqueName, language, directoryNameOpt); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); var assemblyName = creationInfo.AssemblyName ?? projectUniqueName; _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectUniqueName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectUniqueName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions); // HACK: update this since we're still on the UI thread. Note we can only update this if we don't have projects -- the workspace // only lets us really do this with OnSolutionAdded for now. string solutionPathToSetWithOnSolutionAdded = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null && ErrorHandler.Succeeded(solution.GetSolutionInfo(out _, out var solutionFilePath, out _))) { if (w.CurrentSolution.FilePath != solutionFilePath && w.CurrentSolution.ProjectIds.Count == 0) { solutionPathToSetWithOnSolutionAdded = solutionFilePath; } } if (solutionPathToSetWithOnSolutionAdded != null) { w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionPathToSetWithOnSolutionAdded), VersionStamp.Create(), solutionPathToSetWithOnSolutionAdded, projects: new[] { projectInfo })); } else { w.OnProjectAdded(projectInfo); } }); // We do all these sets after the w.OnProjectAdded, as the setting of these properties is going to try to modify the workspace // again. Those modifications will all implicitly do nothing, since the workspace already has the values from above. // We could pass these all through the constructor (but that gets verbose), or have some other control to ignore these, // but that seems like overkill. project.AssemblyName = assemblyName; project.CompilationOptions = creationInfo.CompilationOptions; project.FilePath = creationInfo.FilePath; project.ParseOptions = creationInfo.ParseOptions; return(project); }
public void Create_FilePath(string path) { var info = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, filePath: path); Assert.Equal(path, info.FilePath); }
private async Task <Solution> CreateSolutionAsync(Checksum solutionChecksum, CancellationToken cancellationToken) { var solutionChecksumObject = await RoslynServices.AssetService.GetAssetAsync <SolutionChecksumObject>(solutionChecksum, cancellationToken).ConfigureAwait(false); // TODO: Make these to do work concurrently var workspace = new AdhocWorkspace(RoslynServices.HostServices, workspaceKind: WorkspaceKind_RemoteWorkspace); var solutionInfo = await RoslynServices.AssetService.GetAssetAsync <SolutionChecksumObjectInfo>(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false); var projects = new List <ProjectInfo>(); foreach (var projectChecksum in solutionChecksumObject.Projects) { var projectSnapshot = await RoslynServices.AssetService.GetAssetAsync <ProjectChecksumObject>( projectChecksum, cancellationToken).ConfigureAwait(false); var projectInfo = await RoslynServices.AssetService.GetAssetAsync <ProjectChecksumObjectInfo>( projectSnapshot.Info, cancellationToken).ConfigureAwait(false); if (!workspace.Services.IsSupported(projectInfo.Language)) { // only add project our workspace supports. // workspace doesn't allow creating project with unknown languages continue; } var documents = new List <DocumentInfo>(); foreach (var documentChecksum in projectSnapshot.Documents) { var documentSnapshot = await RoslynServices.AssetService.GetAssetAsync <DocumentChecksumObject>( documentChecksum, cancellationToken).ConfigureAwait(false); var documentInfo = await RoslynServices.AssetService.GetAssetAsync <DocumentChecksumObjectInfo>( documentSnapshot.Info, cancellationToken).ConfigureAwait(false); // TODO: do we need version? documents.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, new RemoteTextLoader(documentSnapshot.Text), documentInfo.FilePath, documentInfo.IsGenerated)); } var p2p = new List <ProjectReference>(); foreach (var checksum in projectSnapshot.ProjectReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await RoslynServices.AssetService.GetAssetAsync <ProjectReference>(checksum, cancellationToken).ConfigureAwait(false); p2p.Add(reference); } var metadata = new List <MetadataReference>(); foreach (var checksum in projectSnapshot.MetadataReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await RoslynServices.AssetService.GetAssetAsync <MetadataReference>(checksum, cancellationToken).ConfigureAwait(false); metadata.Add(reference); } var analyzers = new List <AnalyzerReference>(); foreach (var checksum in projectSnapshot.AnalyzerReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await RoslynServices.AssetService.GetAssetAsync <AnalyzerReference>(checksum, cancellationToken).ConfigureAwait(false); analyzers.Add(reference); } var additionals = new List <DocumentInfo>(); foreach (var documentChecksum in projectSnapshot.AdditionalDocuments) { cancellationToken.ThrowIfCancellationRequested(); var documentSnapshot = await RoslynServices.AssetService.GetAssetAsync <DocumentChecksumObject>(documentChecksum, cancellationToken).ConfigureAwait(false); var documentInfo = await RoslynServices.AssetService.GetAssetAsync <DocumentChecksumObjectInfo>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); // TODO: do we need version? additionals.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, new RemoteTextLoader(documentSnapshot.Text), documentInfo.FilePath, documentInfo.IsGenerated)); } var compilationOptions = await RoslynServices.AssetService.GetAssetAsync <CompilationOptions>(projectSnapshot.CompilationOptions, cancellationToken).ConfigureAwait(false); var parseOptions = await RoslynServices.AssetService.GetAssetAsync <ParseOptions>(projectSnapshot.ParseOptions, cancellationToken).ConfigureAwait(false); projects.Add( ProjectInfo.Create( projectInfo.Id, projectInfo.Version, projectInfo.Name, projectInfo.AssemblyName, projectInfo.Language, projectInfo.FilePath, projectInfo.OutputFilePath, compilationOptions, parseOptions, documents, p2p, metadata, analyzers, additionals, projectInfo.IsSubmission)); } return(workspace.AddSolution(SolutionInfo.Create(solutionInfo.Id, solutionInfo.Version, solutionInfo.FilePath, projects))); }
static IComplierExtension() { _workSpace = new AdhocWorkspace(); _workSpace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId("formatter"), VersionStamp.Default)); }
private async Task SetupCodeControlAsync() { var w = new AdhocWorkspace(Host); w.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Code Project", "code", LanguageNames.CSharp); var w2 = w.CurrentSolution.AddProject(projectInfo); w.TryApplyChanges(w2); DocumentInfo documentInfo; var filename = Filename; if (filename != null) { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular, new FileTextLoader(filename, Encoding.UTF8), filename); } else { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular); } w2 = w.CurrentSolution.AddDocument(documentInfo); w.TryApplyChanges(w2); CodeControl.XOffset = 100; CodeControl.JTF2 = JTF2; CodeControl.PreviewKeyDown += CodeControlOnPreviewKeyDown; var doc = w.CurrentSolution.GetDocument(documentInfo.Id); if (doc != null) { ClassDiagram.Document = doc; CodeControl.Document = doc; var tree = await doc.GetSyntaxTreeAsync(); // ReSharper disable once AssignNullToNotNullAttribute CodeControl.SyntaxTree = tree; var model = await doc.GetSemanticModelAsync(); // ReSharper disable once AssignNullToNotNullAttribute CodeControl.SemanticModel = model; CodeControl.Compilation = model.Compilation; } DateTime startTime = default; CodeControl.AddHandler(RoslynCodeBase.RenderStartEvent, new RoutedEventHandler((sender, args) => { startTime = DateTime.Now; Debug.WriteLine("render start"); })); CodeControl.AddHandler(RoslynCodeBase.RenderCompleteEvent, new RoutedEventHandler((sender, args) => { var span = DateTime.Now - startTime; var msg = $"render complete time is {span}"; Debug.WriteLine(msg); ProtoLogger.Instance.LogAction(msg); })); await CodeControl.UpdateFormattedTextAsync(); CodeControlRendered = true; Rendering.Visibility = Visibility.Collapsed; }
private static SolutionInfo DedupeReferences(SolutionInfo solution) { return(SolutionInfo.Create(solution.Id, solution.Version, solution.FilePath, solution.Projects.Select(DedupeReferences))); }
/// <summary> /// Fidns references using Roslyn by the Unity Coroutine paradigm. When Enumator returns, then a frame should be skipped. /// </summary> /// <param name="asset"></param> /// <param name="results"></param> public static IEnumerator <State> FindReferencesEnumerator(UnityEngine.Object asset, List <AnalyticResult> results) { Stopwatch w = new Stopwatch(); w.Start(); //Get the parts if (asset is MonoBehaviour monoBehaviour) { asset = MonoScript.FromMonoBehaviour(monoBehaviour); } else if (asset is ScriptableObject scriptableObject) { asset = MonoScript.FromScriptableObject(scriptableObject); } //Make sure its a monoscript if (!(asset is MonoScript)) { throw new ArgumentException("Supplied argument is not a MonoScript"); } var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); string scriptPath = Path.GetFullPath(UnityEditor.AssetDatabase.GetAssetPath(asset)); //Prepare paths string folder = Application.dataPath + "/../"; string projectPath = Directory.EnumerateFiles(folder, "Assembly-CSharp.csproj", SearchOption.TopDirectoryOnly).First(); //projectPath = @"D:\Users\Lachee\Documents\Unity Projects\DistanceJam\Assembly-CSharp.csproj"; //Prepare workspace workspace.ClearSolution(); //Prepare solution var solId = SolutionId.CreateNewId(); var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Default); var solution = workspace.AddSolution(solutionInfo); //Prepare the project var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "Assembly-CSharp", "Assembly-CSharp", "C#", projectPath); var project = workspace.AddProject(projectInfo); yield return(State.ReadingFile); //Prepare the documents Document sourceDocument = null; XmlDocument xml = new XmlDocument(); xml.Load(projectPath); var elements = xml.GetElementsByTagName("Compile"); foreach (XmlElement element in elements) { var includePath = Path.GetFullPath(Path.GetDirectoryName(projectPath) + "/" + element.GetAttribute("Include")); //workspace.AddDocument(compileDocument); var name = Path.GetFileName(includePath); var fileContent = File.ReadAllText(includePath); var src = SourceText.From(fileContent); var doc = project.AddDocument(name, src, filePath: includePath); project = doc.Project; if (includePath.Equals(scriptPath)) { sourceDocument = doc; } yield return(State.ReadingFile); } workspace.TryApplyChanges(solution); if (sourceDocument != null) { //Find the model var modelAwait = sourceDocument.GetSemanticModelAsync().ConfigureAwait(false); while (!modelAwait.GetAwaiter().IsCompleted) { yield return(State.FindingModel); } var model = modelAwait.GetAwaiter().GetResult(); //Find hte root var rootAwait = sourceDocument.GetSyntaxRootAsync().ConfigureAwait(false); while (!rootAwait.GetAwaiter().IsCompleted) { yield return(State.FindingRoot); } var root = rootAwait.GetAwaiter().GetResult(); //Find the symbol var syntax = root.DescendantNodes().OfType <ClassDeclarationSyntax>().First(); var symbol = model.GetDeclaredSymbol(syntax); //Find the references var referencesAwait = SymbolFinder.FindReferencesAsync(symbol, sourceDocument.Project.Solution).ConfigureAwait(false); while (!referencesAwait.GetAwaiter().IsCompleted) { yield return(State.FindingSymbol); } var references = referencesAwait.GetAwaiter().GetResult(); results.AddRange(references.SelectMany(s => s.Locations).Select(loc => new AnalyticResult(loc))); } yield return(State.Done); }
/// <summary> /// Finds references using Roslyn by the async paradigm. /// </summary> /// <param name="asset"></param> /// <returns></returns> public static async Task <IEnumerable <AnalyticResult> > FindReferencesAsync(UnityEngine.Object asset) { //Get the parts if (asset is MonoBehaviour monoBehaviour) { asset = MonoScript.FromMonoBehaviour(monoBehaviour); } else if (asset is ScriptableObject scriptableObject) { asset = MonoScript.FromScriptableObject(scriptableObject); } //Make sure its a monoscript if (!(asset is MonoScript)) { throw new ArgumentException("Supplied argument is not a MonoScript"); } var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); string scriptPath = Path.GetFullPath(UnityEditor.AssetDatabase.GetAssetPath(asset)); //Prepare paths string folder = Application.dataPath + "/../"; string projectPath = Directory.EnumerateFiles(folder, "*.csproj", SearchOption.TopDirectoryOnly).First(); projectPath = @"D:\Users\Lachee\Documents\Unity Projects\DistanceJam\Assembly-CSharp.csproj"; //Prepare workspace var workspace = new AdhocWorkspace(); //Prepare solution var solId = SolutionId.CreateNewId(); var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Default); var solution = workspace.AddSolution(solutionInfo); //Prepare the project var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "Assembly-CSharp", "Assembly-CSharp", "C#", projectPath); var project = workspace.AddProject(projectInfo); //Prepare the documents Document sourceDocument = null; await Task.Run(() => { XmlDocument xml = new XmlDocument(); xml.Load(projectPath); var elements = xml.GetElementsByTagName("Compile"); foreach (XmlElement element in elements) { var includePath = Path.GetFullPath(Path.GetDirectoryName(projectPath) + "/" + element.GetAttribute("Include")); //workspace.AddDocument(compileDocument); var name = Path.GetFileName(includePath); var fileContent = File.ReadAllText(includePath); var src = SourceText.From(fileContent); var doc = project.AddDocument(name, src, filePath: includePath); project = doc.Project; if (includePath.Equals(scriptPath)) { sourceDocument = doc; } } }); workspace.TryApplyChanges(solution); if (sourceDocument == null) { return(null); } var model = await sourceDocument.GetSemanticModelAsync(); //Get the semantic model var root = await sourceDocument.GetSyntaxRootAsync(); //Get the syntax var syntax = root.DescendantNodes().OfType <ClassDeclarationSyntax>().First(); //Find the first ClassDeclaration within the syntax var symbol = model.GetDeclaredSymbol(syntax); //Get the symbol based of the class declaration var references = await SymbolFinder.FindReferencesAsync(symbol, sourceDocument.Project.Solution); //Find references return(references.SelectMany(s => s.Locations).Select(loc => new AnalyticResult(loc))); }
public async Task <VisualStudioProject> CreateAndAddToWorkspaceAsync( string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo, CancellationToken cancellationToken) { // HACK: Fetch this service to ensure it's still created on the UI thread; once this is // moved off we'll need to fix up it's constructor to be free-threaded. await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); _visualStudioWorkspaceImpl.SubscribeExternalErrorDiagnosticUpdateSourceToSolutionBuildEvents(); // Since we're on the UI thread here anyways, use that as an opportunity to grab the // IVsSolution object and solution file path. // // ConfigureAwait(true) as we have to come back to the UI thread to do the cast to IVsSolution2. var solution = (IVsSolution2?)await _serviceProvider.GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(true); var solutionFilePath = solution != null && ErrorHandler.Succeeded(solution.GetSolutionInfo(out _, out var filePath, out _)) ? filePath : null; // Following can be off the UI thread. await TaskScheduler.Default; // From this point on, we start mutating the solution. So make us non cancellable. cancellationToken = CancellationToken.None; var id = ProjectId.CreateNewId(projectSystemName); var assemblyName = creationInfo.AssemblyName ?? projectSystemName; // We will use the project system name as the default display name of the project var project = new VisualStudioProject( _visualStudioWorkspaceImpl, _dynamicFileInfoProviders, _hostDiagnosticUpdateSource, id, displayName: projectSystemName, language, assemblyName: assemblyName, compilationOptions: creationInfo.CompilationOptions, filePath: creationInfo.FilePath, parseOptions: creationInfo.ParseOptions); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); await _visualStudioWorkspaceImpl.ApplyChangeToWorkspaceAsync(w => { _visualStudioWorkspaceImpl.AddProjectToInternalMaps_NoLock(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName); var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectSystemName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions) .WithTelemetryId(creationInfo.ProjectGuid); // If we don't have any projects and this is our first project being added, then we'll create a new SolutionId // and count this as the solution being added so that event is raised. if (w.CurrentSolution.ProjectIds.Count == 0) { var solutionSessionId = GetSolutionSessionId(); w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionFilePath), VersionStamp.Create(), solutionFilePath, projects: new[] { projectInfo }, analyzerReferences: w.CurrentSolution.AnalyzerReferences) .WithTelemetryId(solutionSessionId)); } else { w.OnProjectAdded(projectInfo); } }).ConfigureAwait(false); // Ensure that other VS contexts get accurate information that the UIContext for this language is now active. // This is not cancellable as we have already mutated the solution. await _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync(language, CancellationToken.None).ConfigureAwait(false); return(project);
/// <summary> /// Create a <see cref="Solution"/> for <paramref name="code"/> /// Each unique namespace in <paramref name="code"/> is added as a project. /// </summary> /// <param name="code">The code to create the solution from.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> /// <param name="metadataReferences">The metadata references.</param> /// <param name="languageVersion">The <see cref="LanguageVersion"/>.</param> /// <returns>A <see cref="Solution"/>.</returns> public static Solution CreateSolution(IEnumerable <string> code, CSharpCompilationOptions compilationOptions, IEnumerable <MetadataReference>?metadataReferences = null, LanguageVersion languageVersion = LanguageVersion.Latest) { var solutionInfo = SolutionInfo.Create( SolutionId.CreateNewId("Test.sln"), VersionStamp.Default, projects: GetProjectInfos()); var solution = EmptySolution; foreach (var projectInfo in solutionInfo.Projects) { solution = solution.AddProject(projectInfo.WithProjectReferences(FindReferences(projectInfo))); } return(solution); IEnumerable <ProjectInfo> GetProjectInfos() { var byNamespace = new SortedDictionary <string, List <string> >(); foreach (var document in code) { var ns = CodeReader.Namespace(document); if (byNamespace.TryGetValue(ns, out var doc)) { doc.Add(document); } else { byNamespace[ns] = new List <string> { document }; } } var byProject = new SortedDictionary <string, List <KeyValuePair <string, List <string> > > >(); foreach (var kvp in byNamespace) { var last = byProject.Keys.LastOrDefault(); var ns = kvp.Key; if (last != null && ns.Contains(last)) { byProject[last].Add(kvp); } else { byProject.Add(ns, new List <KeyValuePair <string, List <string> > > { kvp }); } } foreach (var kvp in byProject) { var assemblyName = kvp.Key; var projectId = ProjectId.CreateNewId(assemblyName); yield return(ProjectInfo.Create( projectId, VersionStamp.Default, assemblyName, assemblyName, LanguageNames.CSharp, compilationOptions: compilationOptions, metadataReferences: metadataReferences, documents: kvp.Value.SelectMany(x => x.Value) .Select( x => { var documentName = CodeReader.FileName(x); return DocumentInfo.Create( DocumentId.CreateNewId(projectId, documentName), documentName, sourceCodeKind: SourceCodeKind.Regular, loader: new StringLoader(x)); })) .WithParseOptions(CSharpParseOptions.Default.WithLanguageVersion(languageVersion))); } } IEnumerable <ProjectReference> FindReferences(ProjectInfo projectInfo) { var references = new List <ProjectReference>(); foreach (var other in solutionInfo.Projects.Where(x => x.Id != projectInfo.Id)) { if (projectInfo.Documents.Any(x => x.TextLoader is StringLoader stringLoader && (stringLoader.Code.Contains($"using {other.Name};") || stringLoader.Code.Contains($"{other.Name}.")))) { references.Add(new ProjectReference(other.Id)); } } return(references); } }
public async Task CreateScenario() { var logger = new Mock <ILogger>().Object; var workspace = new AdhocWorkspace(); var solutionScenario = SolutionInfo.Create( SolutionId.CreateNewId(), VersionStamp.Create() ); var solution = workspace.AddSolution(solutionScenario); ProjectInfo projectScenario = ProjectInfo.Create( ProjectId.CreateNewId(), VersionStamp.Create(), "CSharpRoslynChangeHandlerTests_Project", "...", LanguageNames.CSharp ); solution = solution.AddProject(projectScenario); #region Test Class SourceText sourceText = SourceText.From($@" using Microsoft.VisualStudio.TestTools.UnitTesting; public class TestClass {{ [TestMethod] public void {TESTMETHOD1_NAME}() {{ }} [TestMethod] public void {TESTMETHOD2_NAME}() {{ ScenarioClass.{SCENARIOMETHOD1_NAME}(); }} }} "); _documentId = DocumentId.CreateNewId(solution.ProjectIds[0]); solution = solution.AddDocument(_documentId, DOCUMENT_TEST, sourceText); #endregion #region Other Class sourceText = SourceText.From($@" public static class ScenarioClass {{ public static void {SCENARIOMETHOD1_NAME}() {{ }} }} "); _documentId = DocumentId.CreateNewId(solution.ProjectIds[0]); _solution = solution.AddDocument(_documentId, DOCUMENT_SCENARIO, sourceText); #endregion workspace.TryApplyChanges(_solution); _workspace = workspace; _handler = new CSharpRoslynChangeHandler(logger); await _handler.Initialize(_workspace.CurrentSolution); }
internal static async Task <Regex> SourceGenRegexAsync( string pattern, RegexOptions?options = null, TimeSpan?matchTimeout = null, CancellationToken cancellationToken = default) { Assert.True(options is not null || matchTimeout is null); string attr = $"[RegexGenerator({SymbolDisplay.FormatLiteral(pattern, quote: true)}"; if (options is not null) { attr += $", {string.Join(" | ", options.ToString().Split(',').Select(o => $"RegexOptions.{o.Trim()}"))}"; if (matchTimeout is not null) { attr += string.Create(CultureInfo.InvariantCulture, $", {(int)matchTimeout.Value.TotalMilliseconds}"); } } attr += ")]"; // Create the source boilerplate for the pattern string code = $@" using System.Text.RegularExpressions; public partial class C {{ {attr} public static partial Regex Get(); }}"; // Use a cached compilation to save a little time. Rather than creating an entirely new workspace // for each test, just create a single compilation, cache it, and then replace its syntax tree // on each test. if (s_compilation is not Compilation comp) { // Create the project containing the source. var proj = new AdhocWorkspace() .AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())) .AddProject("Test", "test.dll", "C#") .WithMetadataReferences(s_refs) .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithNullableContextOptions(NullableContextOptions.Enable)) .WithParseOptions(new CSharpParseOptions(LanguageVersion.Preview)) .AddDocument("RegexGenerator.g.cs", SourceText.From("// Empty", Encoding.UTF8)).Project; Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution)); s_compilation = comp = await proj !.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false); Debug.Assert(comp is not null); } comp = comp.ReplaceSyntaxTree(comp.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(SourceText.From(code, Encoding.UTF8), s_previewParseOptions)); // Run the generator GeneratorDriverRunResult generatorResults = s_generatorDriver.RunGenerators(comp !, cancellationToken).GetRunResult(); if (generatorResults.Diagnostics.Length != 0) { throw new ArgumentException( string.Join(Environment.NewLine, generatorResults.Diagnostics) + Environment.NewLine + string.Join(Environment.NewLine, generatorResults.GeneratedTrees.Select(t => NumberLines(t.ToString())))); } // Compile the assembly to a stream var dll = new MemoryStream(); comp = comp.AddSyntaxTrees(generatorResults.GeneratedTrees.ToArray()); EmitResult results = comp.Emit(dll, options: s_emitOptions, cancellationToken: cancellationToken); if (!results.Success || results.Diagnostics.Length != 0) { throw new ArgumentException( string.Join(Environment.NewLine, results.Diagnostics.Concat(generatorResults.Diagnostics)) + Environment.NewLine + string.Join(Environment.NewLine, generatorResults.GeneratedTrees.Select(t => NumberLines(t.ToString())))); } dll.Position = 0; // Load the assembly into its own AssemblyLoadContext. var alc = new RegexLoadContext(Environment.CurrentDirectory); Assembly a = alc.LoadFromStream(dll); // Instantiate a regex using the newly created static Get method that was source generated. Regex r = (Regex)a.GetType("C") !.GetMethod("Get") !.Invoke(null, null) !; // Issue an unload on the ALC, so it'll be collected once the Regex instance is collected alc.Unload(); return(r); }
internal void AddTestSolution(TestHostSolution solution) { this.OnSolutionAdded(SolutionInfo.Create(solution.Id, solution.Version, solution.FilePath, projects: solution.Projects.Select(p => p.ToProjectInfo()))); }
internal async Task <(Compilation compilation, List <MetadataReference> metadata)> CreateCompilationAsync(IEnumerable <string> paths, IEnumerable <string> assemblies, IEnumerable <string> preprocessors = null, Regex[] filters = null) { Console.WriteLine("Creating workspace..."); var ws = new AdhocWorkspace(); var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default); ws.AddSolution(solutionInfo); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "CSharpExample", "CSharpExample", "C#"); ws.AddProject(projectInfo); if (paths != null) { foreach (var path in paths) { if (path.StartsWith("http://") || path.StartsWith("https://")) { await DownloadDocumentsAsync(path, ws, projectInfo.Id, filters).ConfigureAwait(false); } else if (path.EndsWith(".zip")) { LoadCompressedDocuments(path, ws, projectInfo.Id, filters); } else { LoadFolderDocuments(path, ws, projectInfo.Id, filters); } } } Console.WriteLine("Compiling..."); var project = ws.CurrentSolution.Projects.Single(); List <MetadataReference> metadata = new List <MetadataReference>(); if (assemblies != null) { foreach (var assm in assemblies) { IEnumerable <FileInfo> files = Enumerable.Empty <FileInfo>(); if (File.Exists(assm)) { files = new FileInfo[] { new FileInfo(assm) }; } else { string recursive = Path.DirectorySeparatorChar + "**" + Path.DirectorySeparatorChar; bool isRecursive = false; var d = assm; var fn = Path.GetFileName(assm); if (d.Contains(recursive)) { d = d.Substring(0, d.IndexOf(recursive)); isRecursive = true; } else if (Directory.Exists(d)) { fn = null; } else { d = Path.GetDirectoryName(d); } var dir = new DirectoryInfo(d); if (!dir.Exists) { throw new DirectoryNotFoundException(d); } if (string.IsNullOrEmpty(fn)) { files = dir.GetFiles("*.dll", isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } else { var di = new DirectoryInfo(d); files = dir.GetFiles(fn, isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } } foreach (var item in files) { var metaref = MetadataReference.CreateFromFile(item.FullName); project = project.AddMetadataReference(metaref); metadata.Add(metaref); } } } //Ensure mscorlib is referenced string mscorlib = typeof(System.Enum).Assembly.Location; if (File.Exists(mscorlib)) { project = project.WithParseOptions(new Microsoft.CodeAnalysis.CSharp.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest, DocumentationMode.Parse, SourceCodeKind.Regular, preprocessors)); var metaref = MetadataReference.CreateFromFile(mscorlib); project = project.AddMetadataReference(metaref); } var comp = await project.GetCompilationAsync().ConfigureAwait(false); return(comp, metadata); }
static ICompilerExtension() { _workSpace = new AdhocWorkspace(); _workSpace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId("formatter"), VersionStamp.Default)); _options = new CSharpParseOptions(LanguageVersion.Latest); }
static CSharpSyntaxBase() { _workSpace = new AdhocWorkspace(); _workSpace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId("formatter"), VersionStamp.Default)); _options = new CSharpParseOptions(LanguageVersion.Latest, preprocessorSymbols: new[] { "RELEASE" }); }
public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo) { // HACK: Fetch this service to ensure it's still created on the UI thread; once this is moved off we'll need to fix up it's constructor to be free-threaded. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); // HACK: since we're on the UI thread, ensure we initialize our options provider which depends on a UI-affinitized experimentation service _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitialized(); var id = ProjectId.CreateNewId(projectSystemName); var assemblyName = creationInfo.AssemblyName ?? projectSystemName; // We will use the project system name as the default display name of the project var project = new VisualStudioProject( _visualStudioWorkspaceImpl, _dynamicFileInfoProviders, _hostDiagnosticUpdateSource, id, displayName: projectSystemName, language, assemblyName: assemblyName, compilationOptions: creationInfo.CompilationOptions, filePath: creationInfo.FilePath, parseOptions: creationInfo.ParseOptions); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectSystemName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions) .WithTelemetryId(creationInfo.ProjectGuid); // If we don't have any projects and this is our first project being added, then we'll create a new SolutionId if (w.CurrentSolution.ProjectIds.Count == 0) { // Fetch the current solution path. Since we're on the UI thread right now, we can do that. string?solutionFilePath = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null) { if (ErrorHandler.Failed(solution.GetSolutionInfo(out _, out solutionFilePath, out _))) { // Paranoia: if the call failed, we definitely don't want to use any stuff that was set solutionFilePath = null; } } var solutionSessionId = GetSolutionSessionId(); w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionFilePath), VersionStamp.Create(), solutionFilePath, projects: new[] { projectInfo }, analyzerReferences: w.CurrentSolution.AnalyzerReferences) .WithTelemetryId(solutionSessionId)); } else { w.OnProjectAdded(projectInfo); } _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguage(language); }); return(project);
/// <summary> /// Open a solution file and all referenced projects. /// </summary> public async Task <Solution> OpenSolutionAsync(string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException("solutionFilePath"); } this.ClearSolution(); solutionFilePath = Path.GetFullPath(solutionFilePath); using (this.dataGuard.DisposableWait()) { this.SetSolutionProperties(solutionFilePath); } VersionStamp version = default(VersionStamp); SolutionFile solutionFile = null; using (var reader = new StreamReader(solutionFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath)); var text = await reader.ReadToEndAsync().ConfigureAwait(false); solutionFile = SolutionFile.Parse(new StringReader(text)); } var solutionFolder = Path.GetDirectoryName(solutionFilePath); // seed loaders from known project types using (this.dataGuard.DisposableWait()) { foreach (var projectBlock in solutionFile.ProjectBlocks) { var absoluteProjectPath = GetAbsolutePath(projectBlock.ProjectPath, solutionFolder); var loader = GetLoaderFromProjectType(projectBlock.ProjectTypeGuid); this.projectPathToLoaderMap[absoluteProjectPath] = loader; } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); // load all the projects foreach (var projectBlock in solutionFile.ProjectBlocks) { cancellationToken.ThrowIfCancellationRequested(); var absoluteProjectPath = GetAbsolutePath(projectBlock.ProjectPath, solutionFolder); // don't even try to load project if there is no file if (!File.Exists(absoluteProjectPath)) { continue; } var loader = GetLoaderFromProjectPath(absoluteProjectPath); // only attempt to load project if it can be loaded. if (loader != null) { // projects get added to pending projects as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } // have the base workspace construct the solution from this info this.OnSolutionAdded(SolutionInfo.Create(SolutionId.CreateNewId(debugName: solutionFilePath), version, solutionFilePath, loadedProjects)); return(this.CurrentSolution); }
/// <summary> /// Open a solution file and all referenced projects. /// </summary> public async Task <Solution> OpenSolutionAsync(string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } this.ClearSolution(); var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory()); using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } VersionStamp version = default(VersionStamp); #if !MSBUILD12 Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; var invalidProjects = new List <ProjectInSolution>(); // seed loaders from known project types using (_dataGuard.DisposableWait(cancellationToken)) { foreach (var project in solutionFile.ProjectsInOrder) { if (project.ProjectType == SolutionProjectType.SolutionFolder) { continue; } var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { var extension = Path.GetExtension(projectAbsolutePath); if (extension.Length > 0 && extension[0] == '.') { extension = extension.Substring(1); } var loader = ProjectFileLoader.GetLoaderForProjectFileExtension(this, extension); if (loader != null) { _projectPathToLoaderMap[projectAbsolutePath] = loader; } } else { invalidProjects.Add(project); } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != SolutionProjectType.SolutionFolder && !invalidProjects.Contains(project)) { var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } } #else SolutionFile solutionFile = null; using (var reader = new StreamReader(absoluteSolutionPath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath)); var text = await reader.ReadToEndAsync().ConfigureAwait(false); solutionFile = SolutionFile.Parse(new StringReader(text)); } var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath); // seed loaders from known project types using (_dataGuard.DisposableWait()) { foreach (var projectBlock in solutionFile.ProjectBlocks) { string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, ReportMode.Ignore, out absoluteProjectPath)) { var loader = ProjectFileLoader.GetLoaderForProjectTypeGuid(this, projectBlock.ProjectTypeGuid); if (loader != null) { _projectPathToLoaderMap[absoluteProjectPath] = loader; } } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // load all the projects foreach (var projectBlock in solutionFile.ProjectBlocks) { cancellationToken.ThrowIfCancellationRequested(); string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath)) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } #endif // construct workspace from loaded project infos this.OnSolutionAdded(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects)); this.UpdateReferencesAfterAdd(); return(this.CurrentSolution); }
internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments( IEnumerable <AbstractProject> projects) { AssertIsForeground(); // If the workspace host isn't actually ready yet, we shouldn't do anything. // Also, if the solution is closing we shouldn't do anything either, because all of our state is // in the process of going away. This can happen if we receive notification that a document has // opened in the middle of the solution close operation. if (!this.HostReadyForEvents || _tracker._solutionIsClosing) { return; } // We need to push these projects and any project dependencies we already know about. Therefore, compute the // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order. var visited = new HashSet <AbstractProject>(); var inOrderToPush = new List <AbstractProject>(); foreach (var project in projects) { AddToPushListIfNeeded(project, inOrderToPush, visited); } var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray(); // We need to enable projects to start pushing changes to workspace hosts even before we add the solution/project to the host. // This is required because between the point we capture the project info for current state and the point where we start pushing to workspace hosts, // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject. // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks. foreach (var project in inOrderToPush) { project.StartPushingToWorkspaceHosts(); } if (!_solutionAdded) { string solutionFilePath = null; VersionStamp?version = default(VersionStamp?); // Figure out the solution version if (ErrorHandler.Succeeded(_tracker._vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null) { solutionFilePath = Path.Combine(solutionDirectory, solutionFileName); if (File.Exists(solutionFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath)); } } if (version == null) { version = VersionStamp.Create(); } var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName); _tracker.RegisterSolutionProperties(id); var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos); this.Host.OnSolutionAdded(solutionInfo); _solutionAdded = true; } else { // The solution is already added, so we'll just do project added notifications from here foreach (var projectInfo in projectInfos) { this.Host.OnProjectAdded(projectInfo); } } foreach (var project in inOrderToPush) { _pushedProjects.Add(project); foreach (var document in project.GetCurrentDocuments()) { if (document.IsOpen) { this.Host.OnDocumentOpened( document.Id, document.GetOpenTextBuffer(), isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _tracker._runningDocumentTable)); } } } }
private async Task <Solution> GetSolutionAsync(IRemotableDataService service, PinnedRemotableDataScope syncScope) { var workspace = new AdhocWorkspace(); var solutionObject = await service.GetValueAsync <SolutionStateChecksums>(syncScope.SolutionChecksum); var solutionInfo = await service.GetValueAsync <SolutionInfo.SolutionAttributes>(solutionObject.Info).ConfigureAwait(false); var projects = new List <ProjectInfo>(); foreach (var projectObject in solutionObject.Projects.ToProjectObjects(service)) { var projectInfo = await service.GetValueAsync <ProjectInfo.ProjectAttributes>(projectObject.Info).ConfigureAwait(false); if (!workspace.Services.IsSupported(projectInfo.Language)) { continue; } var documents = new List <DocumentInfo>(); foreach (var documentObject in projectObject.Documents.ToDocumentObjects(service)) { var documentInfo = await service.GetValueAsync <DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false); var text = await service.GetValueAsync <SourceText>(documentObject.Text).ConfigureAwait(false); // TODO: do we need version? documents.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())), documentInfo.FilePath, documentInfo.IsGenerated)); } var p2p = new List <ProjectReference>(); foreach (var checksum in projectObject.ProjectReferences) { var reference = await service.GetValueAsync <ProjectReference>(checksum).ConfigureAwait(false); p2p.Add(reference); } var metadata = new List <MetadataReference>(); foreach (var checksum in projectObject.MetadataReferences) { var reference = await service.GetValueAsync <MetadataReference>(checksum).ConfigureAwait(false); metadata.Add(reference); } var analyzers = new List <AnalyzerReference>(); foreach (var checksum in projectObject.AnalyzerReferences) { var reference = await service.GetValueAsync <AnalyzerReference>(checksum).ConfigureAwait(false); analyzers.Add(reference); } var additionals = new List <DocumentInfo>(); foreach (var documentObject in projectObject.AdditionalDocuments.ToDocumentObjects(service)) { var documentInfo = await service.GetValueAsync <DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false); var text = await service.GetValueAsync <SourceText>(documentObject.Text).ConfigureAwait(false); // TODO: do we need version? additionals.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, TextLoader.From(TextAndVersion.Create(text, VersionStamp.Create())), documentInfo.FilePath, documentInfo.IsGenerated)); } var compilationOptions = await service.GetValueAsync <CompilationOptions>(projectObject.CompilationOptions).ConfigureAwait(false); var parseOptions = await service.GetValueAsync <ParseOptions>(projectObject.ParseOptions).ConfigureAwait(false); projects.Add( ProjectInfo.Create( projectInfo.Id, projectInfo.Version, projectInfo.Name, projectInfo.AssemblyName, projectInfo.Language, projectInfo.FilePath, projectInfo.OutputFilePath, compilationOptions, parseOptions, documents, p2p, metadata, analyzers, additionals, projectInfo.IsSubmission)); } return(workspace.AddSolution(SolutionInfo.Create(solutionInfo.Id, solutionInfo.Version, solutionInfo.FilePath, projects))); }
/// <summary> /// Loads the <see cref="SolutionInfo"/> for the specified solution file, including all projects referenced by the solution file and /// all the projects referenced by the project files. /// </summary> public async Task <SolutionInfo> LoadSolutionInfoAsync( string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Directory.GetCurrentDirectory()); using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } VersionStamp version = default(VersionStamp); #if !MSBUILD12 Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // a list to accumulate all the loaded projects var loadedProjects = new LoadState(null); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != SolutionProjectType.SolutionFolder) { var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never prefer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } } #else SolutionFile solutionFile = null; using (var reader = new StreamReader(absoluteSolutionPath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath)); var text = await reader.ReadToEndAsync().ConfigureAwait(false); solutionFile = SolutionFile.Parse(new StringReader(text)); } var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath); // a list to accumulate all the loaded projects var loadedProjects = new LoadState(null); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // load all the projects foreach (var projectBlock in solutionFile.ProjectBlocks) { cancellationToken.ThrowIfCancellationRequested(); string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath)) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never prefer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } #endif // construct workspace from loaded project infos return(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects.Projects)); }
public async Task <SolutionInfo> LoadSolutionInfoAsync( string solutionFilePath, IProgress <ProjectLoadProgress>?progress = null, ILogger?msbuildLogger = null, CancellationToken cancellationToken = default) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } if (!_pathResolver.TryGetAbsoluteSolutionPath(solutionFilePath, baseDirectory: Directory.GetCurrentDirectory(), DiagnosticReportingMode.Throw, out var absoluteSolutionPath)) { // TryGetAbsoluteSolutionPath should throw before we get here. return(null !); } using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } var solutionFile = MSB.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportingMode = GetReportingModeForUnrecognizedProjects(); var reportingOptions = new DiagnosticReportingOptions( onPathFailure: reportingMode, onLoaderFailure: reportingMode); var projectPaths = ImmutableArray.CreateBuilder <string>(); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != MSB.Construction.SolutionProjectType.SolutionFolder) { projectPaths.Add(project.RelativePath); } } var buildManager = new ProjectBuildManager(_properties, msbuildLogger); var worker = new Worker( _workspaceServices, _diagnosticReporter, _pathResolver, _projectFileLoaderRegistry, buildManager, projectPaths.ToImmutable(), // TryGetAbsoluteSolutionPath should not return an invalid path baseDirectory: Path.GetDirectoryName(absoluteSolutionPath) !, _properties, projectMap: null, progress, requestedProjectOptions: reportingOptions, discoveredProjectOptions: reportingOptions, preferMetadataForReferencesOfDiscoveredProjects: false); var projects = await worker.LoadAsync(cancellationToken).ConfigureAwait(false); // construct workspace from loaded project infos return(SolutionInfo.Create( SolutionId.CreateNewId(debugName: absoluteSolutionPath), version: default,
private async Task <Solution> CreateSolutionAsync(Checksum solutionChecksum, CancellationToken cancellationToken) { // synchronize whole solution first await _assetService.SynchronizeSolutionAssetsAsync(solutionChecksum, cancellationToken).ConfigureAwait(false); var solutionChecksumObject = await _assetService.GetAssetAsync <SolutionStateChecksums>(solutionChecksum, cancellationToken).ConfigureAwait(false); var workspace = new AdhocWorkspace(RoslynServices.HostServices, workspaceKind: WorkspaceKind_RemoteWorkspace); // never cache any tree in memory workspace.Options = workspace.Options.WithChangedOption(CacheOptions.RecoverableTreeLengthThreshold, 0); var solutionInfo = await _assetService.GetAssetAsync <SolutionInfo.SolutionAttributes>(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false); var projects = new List <ProjectInfo>(); foreach (var projectChecksum in solutionChecksumObject.Projects) { var projectSnapshot = await _assetService.GetAssetAsync <ProjectStateChecksums>(projectChecksum, cancellationToken).ConfigureAwait(false); var projectInfo = await _assetService.GetAssetAsync <ProjectInfo.ProjectAttributes>(projectSnapshot.Info, cancellationToken).ConfigureAwait(false); if (!workspace.Services.IsSupported(projectInfo.Language)) { // only add project our workspace supports. // workspace doesn't allow creating project with unknown languages continue; } var documents = new List <DocumentInfo>(); foreach (var documentChecksum in projectSnapshot.Documents) { var documentSnapshot = await _assetService.GetAssetAsync <DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false); var documentInfo = await _assetService.GetAssetAsync <DocumentInfo.DocumentAttributes>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); var textLoader = TextLoader.From( TextAndVersion.Create( new ChecksumSourceText( documentSnapshot.Text, await _assetService.GetAssetAsync <SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false)), VersionStamp.Create(), documentInfo.FilePath)); // TODO: do we need version? documents.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, textLoader, documentInfo.FilePath, documentInfo.IsGenerated)); } var p2p = new List <ProjectReference>(); foreach (var checksum in projectSnapshot.ProjectReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await _assetService.GetAssetAsync <ProjectReference>(checksum, cancellationToken).ConfigureAwait(false); p2p.Add(reference); } var metadata = new List <MetadataReference>(); foreach (var checksum in projectSnapshot.MetadataReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await _assetService.GetAssetAsync <MetadataReference>(checksum, cancellationToken).ConfigureAwait(false); metadata.Add(reference); } var analyzers = new List <AnalyzerReference>(); foreach (var checksum in projectSnapshot.AnalyzerReferences) { cancellationToken.ThrowIfCancellationRequested(); var reference = await _assetService.GetAssetAsync <AnalyzerReference>(checksum, cancellationToken).ConfigureAwait(false); analyzers.Add(reference); } var additionals = new List <DocumentInfo>(); foreach (var documentChecksum in projectSnapshot.AdditionalDocuments) { cancellationToken.ThrowIfCancellationRequested(); var documentSnapshot = await _assetService.GetAssetAsync <DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false); var documentInfo = await _assetService.GetAssetAsync <DocumentInfo.DocumentAttributes>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); var textLoader = TextLoader.From( TextAndVersion.Create( new ChecksumSourceText( documentSnapshot.Text, await _assetService.GetAssetAsync <SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false)), VersionStamp.Create(), documentInfo.FilePath)); // TODO: do we need version? additionals.Add( DocumentInfo.Create( documentInfo.Id, documentInfo.Name, documentInfo.Folders, documentInfo.SourceCodeKind, textLoader, documentInfo.FilePath, documentInfo.IsGenerated)); } var compilationOptions = await _assetService.GetAssetAsync <CompilationOptions>(projectSnapshot.CompilationOptions, cancellationToken).ConfigureAwait(false); var parseOptions = await _assetService.GetAssetAsync <ParseOptions>(projectSnapshot.ParseOptions, cancellationToken).ConfigureAwait(false); projects.Add( ProjectInfo.Create( projectInfo.Id, projectInfo.Version, projectInfo.Name, projectInfo.AssemblyName, projectInfo.Language, projectInfo.FilePath, projectInfo.OutputFilePath, compilationOptions, parseOptions, documents, p2p, metadata, analyzers, additionals, projectInfo.IsSubmission)); } return(workspace.AddSolution(SolutionInfo.Create(solutionInfo.Id, solutionInfo.Version, solutionInfo.FilePath, projects))); }