/// <summary> /// Creates the BuildXL workspace and initializes the language service providers. /// </summary> /// <remarks> /// This must be called when a text document is actually opened. The order VSCode /// calls the plugin is "Initialize" -> "DidConfigurationChange" -> DidOpenTextDocument. /// So, if you attempt to create the workspace, and initialize the providers during the /// initialization phase, then you will not have proper access to any configuration settings /// the user may have made. /// </remarks> private Task <(WorkspaceLoadingState workspaceLoadingState, AppState appState, LanguageServiceProviders languageServiceProviders)> LoadWorkspaceAsync(TextDocumentManager documentManager = null) { var workspaceLoadingTask = m_workspaceLoadingTask.GetOrCreate(async() => { var result = await Task.Run(() => { try { m_progressReporter.ReportWorkspaceInit(); WorkspaceLoadingState workspaceLoadingState; if (m_rootUri == null) { throw new ArgumentException("Root directory was not passed from VSCode via the rootUri configuration value"); } var appState = AppState.TryCreateWorkspace(documentManager, m_rootUri, (s, ea) => { // "Casting" the EventArgs object from the BuildXL library to the "local" version // to avoid pulling in all of its dependencies during build. var rpcEventArgs = BuildXL.Ide.JsonRpc.WorkspaceProgressEventArgs.Create( (BuildXL.Ide.JsonRpc.ProgressStage)ea.ProgressStage, ea.NumberOfProcessedSpecs, ea.TotalNumberOfSpecs); m_progressReporter.ReportWorkspaceInProgress(WorkspaceLoadingParams.InProgress(rpcEventArgs)); }, m_testContext, m_settings); if (appState == null || appState.HasUnrecoverableFailures()) { workspaceLoadingState = WorkspaceLoadingState.Failure; m_progressReporter.ReportWorkspaceFailure(m_tracer.LogFilePath, OpenLogFile); } else { workspaceLoadingState = WorkspaceLoadingState.Success; m_progressReporter.ReportWorkspaceSuccess(); } LanguageServiceProviders providers = null; lock (m_loadWorkspaceLock) { if (workspaceLoadingState == WorkspaceLoadingState.Success) { // In practice you should not make callouts while holding // a lock. Initializing the providers sets members of this // class and also relies on members of the app-state. // So, we do want to block callers until initialization of // the providers is complete, however, be warned that // if a provider ever calls back into the app it could // cause a deadlock. providers = InitializeProviders(appState); } } return(workspaceLoadingState, appState, providers); } catch (Exception e) { var errorMessage = e.ToStringDemystified(); Logger.LanguageServerUnhandledInternalError(LoggingContext, errorMessage); m_progressReporter.ReportWorkspaceFailure(m_tracer.LogFilePath, OpenLogFile); m_testContext.GetValueOrDefault().ErrorReporter?.Invoke(errorMessage); return(WorkspaceLoadingState.Failure, (AppState)null, (LanguageServiceProviders)null); } }); return(result); }); // Changing the workspace loading state once the task is finished. workspaceLoadingTask.ContinueWith(t => { m_workspaceLoadingState = t.Result.Item1; }); return(workspaceLoadingTask); }
public void ReportWorkspaceInProgress(WorkspaceLoadingParams workspcaeLoading) { }