/// <summary> /// Close the open solution, and reset the workspace to a new empty solution. /// </summary> public void CloseSolution() { using (_serializationLock.DisposableWait()) { this.ClearSolution(); } }
/// <summary> /// Associates a project file extension with a language name. /// </summary> public void AssociateFileExtensionWithLanguage(string fileExtension, string language) { using (_dataGuard.DisposableWait()) { _extensionToLanguageMap[fileExtension] = language; } }
internal CodeModelProjectCache GetCodeModelCache() { Contract.ThrowIfNull(_vsProject); Contract.ThrowIfNull(_visualStudioWorkspace); using (_guard.DisposableWait()) { if (_codeModelCache == null) { var project = _visualStudioWorkspace.CurrentSolution.GetProject(_vsProject.Id); if (project == null && !_vsProject.PushingChangesToWorkspaceHosts) { // if this project hasn't been pushed yet, push it now so that the user gets a useful experience here. _vsProject.StartPushingToWorkspaceAndNotifyOfOpenDocuments(); // re-check to see whether we now has the project in the workspace project = _visualStudioWorkspace.CurrentSolution.GetProject(_vsProject.Id); } if (project != null) { _codeModelCache = new CodeModelProjectCache(_vsProject, _serviceProvider, project.LanguageServices, _visualStudioWorkspace); } } return(_codeModelCache); } }
private CodeModelProjectCache GetCodeModelCache() { Contract.ThrowIfNull(_projectId); Contract.ThrowIfNull(_visualStudioWorkspace); using (_guard.DisposableWait()) { if (_codeModelCache == null) { var workspaceProject = _visualStudioWorkspace.CurrentSolution.GetProject(_projectId); var hostProject = _visualStudioWorkspace.GetHostProject(_projectId); if (workspaceProject == null && !hostProject.PushingChangesToWorkspace) { // if this project hasn't been pushed yet, push it now so that the user gets a useful experience here. hostProject.StartPushingToWorkspaceAndNotifyOfOpenDocuments(); // re-check to see whether we now has the project in the workspace workspaceProject = _visualStudioWorkspace.CurrentSolution.GetProject(_projectId); } if (workspaceProject != null) { _codeModelCache = new CodeModelProjectCache(_threadingContext, _projectId, _codeModelInstanceFactory, _serviceProvider, workspaceProject.LanguageServices, _visualStudioWorkspace); } } return(_codeModelCache); } }
public MetadataReference GetAddOrUpdate(string path, MetadataReferenceProperties properties) { using (_gate.DisposableWait()) { WeakReference <MetadataReference> weakref; MetadataReference mref = null; if (!(_references.TryGetValue(properties, out weakref) && weakref.TryGetTarget(out mref))) { // try to base this metadata reference off of an existing one, so we don't load the metadata bytes twice. foreach (var wr in _references.Values) { if (wr.TryGetTarget(out mref)) { mref = mref.WithProperties(properties); break; } } if (mref == null) { mref = _cache._createReference(path, properties); } _references[properties] = new WeakReference <MetadataReference>(mref); } return(mref); } }
private Task?EnsureInstanceIsSavedAsync(T instance) { if (_weakReference == null) { _weakReference = new WeakReference <T>(instance); } else { _weakReference.SetTarget(instance); } if (!_saved) { _saved = true; using (s_taskGuard.DisposableWait()) { // force all save tasks to be in sequence so we don't hog all the threads s_latestTask = s_latestTask.SafeContinueWithFromAsync(t => SaveAsync(instance, CancellationToken.None), CancellationToken.None, TaskScheduler.Default); return(s_latestTask); } } return(null); }
private async void OnEvicted(T instance) { if (!saved) { using (await this.Gate.DisposableWaitAsync(CancellationToken.None).ConfigureAwait(false)) { if (!saved) { Task saveTask; using (taskGuard.DisposableWait()) { // force all save tasks to be in sequence so we don't hog all the threads saveTask = latestTask = latestTask.SafeContinueWith <Task>(t => this.SaveAsync(instance, CancellationToken.None), CancellationToken.None, TaskScheduler.Default).Unwrap(); } // wait for this save to be done await saveTask.ConfigureAwait(false); this.saved = true; } } } }
private CodeModelProjectCache GetCodeModelCache() { Contract.ThrowIfNull(_projectId); Contract.ThrowIfNull(_visualStudioWorkspace); using (_guard.DisposableWait()) { if (_codeModelCache == null) { var workspaceProject = _visualStudioWorkspace.CurrentSolution.GetProject( _projectId ); if (workspaceProject != null) { _codeModelCache = new CodeModelProjectCache( _threadingContext, _projectId, _codeModelInstanceFactory, _projectCodeModelFactory, _serviceProvider, workspaceProject.LanguageServices, _visualStudioWorkspace ); } } return(_codeModelCache); } }
public MetadataReference GetMetadataReference(Compilation compilation, ImmutableArray <string> aliases, bool embedInteropTypes) { var key = new MetadataReferenceProperties(MetadataImageKind.Assembly, aliases, embedInteropTypes); using (gate.DisposableWait()) { WeakReference <MetadataReference> weakMetadata; MetadataReference metadataReference; if (!metadataReferences.TryGetValue(key, out weakMetadata) || !weakMetadata.TryGetTarget(out metadataReference)) { // here we give out strong reference to compilation. so there is possibility that we end up making 2 compilations for same project alive. // one for final compilation and one for declaration only compilation. but the final compilation will be eventually kicked out from compilation cache // if there is no activity on the project. or the declaration compilation will go away if the project that depends on the reference doesn't have any // activity when it is kicked out from compilation cache. if there is an activity, then both will updated as activity happens. // so simply put, things will go away when compilations are kicked out from the cache or due to user activity. // // there is one case where we could have 2 compilations for same project alive. if a user opens a file that requires a skeleton assembly when the skeleton // assembly project didn't reach the final stage yet and then the user opens another document that is part of the skeleton assembly project // and then never change it. declaration compilation will be alive by skeleton assembly and final compilation will be alive by background compiler. metadataReference = this.image.CreateReference(aliases, embedInteropTypes, new DeferredDocumentationProvider(compilation)); weakMetadata = new WeakReference <MetadataReference>(metadataReference); this.metadataReferences[key] = weakMetadata; } return(metadataReference); } }
private Task EnsureInstanceIsSaved(T instance) { if (this.weakInstance == NoReference) { this.weakInstance = new WeakReference <T>(instance); } else { this.weakInstance.SetTarget(instance); } if (!saved) { this.saved = true; using (taskGuard.DisposableWait()) { // force all save tasks to be in sequence so we don't hog all the threads latestTask = latestTask.SafeContinueWithFromAsync(t => this.SaveAsync(instance, CancellationToken.None), CancellationToken.None, TaskScheduler.Default); return(latestTask); } } else { return(null); } }
/// <summary> /// Associates a project file extension with a language name. /// </summary> public void AssociateFileExtensionWithLanguage(string projectFileExtension, string language) { if (language == null) { throw new ArgumentNullException(nameof(language)); } if (projectFileExtension == null) { throw new ArgumentNullException(nameof(projectFileExtension)); } using (_dataGuard.DisposableWait()) { _extensionToLanguageMap[projectFileExtension] = language; } }
protected static Task SaveTreeAsync(SyntaxNode root, ITemporaryStorage storage) { using (taskGuard.DisposableWait()) { // force all save tasks to be in sequence latestTask = latestTask.SafeContinueWith(t => SaveTreeWorkerAsync(root, storage, CancellationToken.None), CancellationToken.None, TaskScheduler.Default).Unwrap(); return(latestTask); } }
public IAsyncToken BeginAsyncOperation(string name, object tag = null, [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) { using (_gate.DisposableWait(CancellationToken.None)) { IAsyncToken asyncToken; if (_trackActiveTokens) { var token = new DiagnosticAsyncToken(this, name, tag, filePath, lineNumber); _diagnosticTokenList.Add(token); asyncToken = token; } else { asyncToken = new AsyncToken(this); } return(asyncToken); } }
public void AddProject(ProjectId projectId, string projectName, string language = LanguageNames.CSharp) { using (_serializationLock.DisposableWait()) { var oldSolution = this.CurrentSolution; var newSolution = this.SetCurrentSolution(oldSolution.AddProject(projectId, projectName, projectName, language)); this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.ProjectAdded, oldSolution, newSolution, projectId); } }
/// <summary> /// Gets the list of projects (topologically sorted) that directly depend on this project. /// </summary> public IImmutableSet <ProjectId> GetProjectsThatDirectlyDependOnThisProject(ProjectId projectId) { if (projectId == null) { throw new ArgumentNullException(nameof(projectId)); } if (_lazyReverseReferencesMap == null) { using (_dataLock.DisposableWait()) { return(this.GetProjectsThatDirectlyDependOnThisProject_NoLock(projectId)); } } else { // okay, because its only ever going to be computed and assigned once return(this.GetProjectsThatDirectlyDependOnThisProject_NoLock(projectId)); } }
private static void ClearQueueWorker <TKey, TValue>(NonReentrantLock gate, Dictionary <TKey, TValue> map, Func <TValue, IDisposable> disposerSelector) { using (gate.DisposableWait(CancellationToken.None)) { foreach (var(_, data) in map) { disposerSelector?.Invoke(data)?.Dispose(); } map.Clear(); } }
private static TValue DequeueWorker <TKey, TValue>(NonReentrantLock gate, Dictionary <TKey, TValue> map, CancellationToken cancellationToken) { using (gate.DisposableWait(cancellationToken)) { var first = default(KeyValuePair <TKey, TValue>); foreach (var kv in map) { first = kv; break; } // this is only one that removes data from the queue. so, it should always succeed var result = map.Remove(first.Key); Debug.Assert(result); return(first.Value); } }
/// <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> /// <param name="solutionFilePath">The path to the solution file to be loaded. This may be an absolute path or a path relative to the /// current working directory.</param> /// <param name="progress">An optional <see cref="IProgress{T}"/> that will receive updates as the solution is loaded.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> to allow cancellation of this operation.</param> public async Task <SolutionInfo> LoadSolutionInfoAsync( string solutionFilePath, IProgress <ProjectLoadProgress> progress = 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); var worker = new Worker( _workspaceServices, _diagnosticReporter, _pathResolver, _projectFileLoaderRegistry, buildManager, projectPaths.ToImmutable(), 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,