예제 #1
0
        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();
        }
예제 #3
0
        /// <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);
                            });
                        }
                    }
                }
            }
        }
예제 #4
0
        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 })));
 }
예제 #6
0
        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);
        }
예제 #7
0
        public void Create_FilePath(string path)
        {
            var info = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, filePath: path);

            Assert.Equal(path, info.FilePath);
        }
예제 #8
0
        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)));
        }
예제 #9
0
 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)));
        }
예제 #14
0
        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);
예제 #15
0
        /// <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);
        }
예제 #17
0
        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);
        }
예제 #18
0
 internal void AddTestSolution(TestHostSolution solution)
 {
     this.OnSolutionAdded(SolutionInfo.Create(solution.Id, solution.Version, solution.FilePath, projects: solution.Projects.Select(p => p.ToProjectInfo())));
 }
예제 #19
0
        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);
        }
예제 #20
0
 static ICompilerExtension()
 {
     _workSpace = new AdhocWorkspace();
     _workSpace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId("formatter"), VersionStamp.Default));
     _options = new CSharpParseOptions(LanguageVersion.Latest);
 }
예제 #21
0
 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);
예제 #23
0
        /// <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);
        }
예제 #24
0
        /// <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);
        }
예제 #25
0
            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));
                        }
                    }
                }
            }
예제 #26
0
        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)));
        }
예제 #27
0
        /// <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,
예제 #29
0
        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)));
        }