private void AddImportTags(ISmartTagSession session, IList<SmartTagActionSet> smartTagActionSets) { var textBuffer = _textBuffer; var span = session.CreateTrackingSpan(textBuffer); var imports = textBuffer.CurrentSnapshot.GetMissingImports(_serviceProvider, span); if (imports == MissingImportAnalysis.Empty) { return; } SmartTagController controller; session.Properties.TryGetProperty<SmartTagController>(typeof(SmartTagController), out controller); if (controller == null) { return; } var task = Volatile.Read(ref controller._curTask); var origTask = task; var snapshot = textBuffer.CurrentSnapshot; if (task != null && task.ApplicableToSpan.GetSpan(snapshot) != imports.ApplicableToSpan.GetSpan(snapshot)) { // Previous task is invalid, so abort it and we'll start a // new one. task.Abort(); session.Properties.RemoveProperty(typeof(SmartTagAugmentTask)); task = null; } if (task == null) { task = new SmartTagAugmentTask( _serviceProvider, textBuffer, session.TextView, imports ); if (Interlocked.CompareExchange(ref controller._curTask, task, origTask) != origTask) { // Item has been changed by someone else, so abort // Except we should always be on the UI thread here, so // there should be no races. Debug.Fail("Race in AugmentSmartTagSession"); return; } } session.ApplicableToSpan = imports.ApplicableToSpan; var result = task.GetResultIfComplete(); if (result != null && Interlocked.CompareExchange(ref controller._curTask, null, task) == task) { // Provide results if we were the current task and we are // now complete smartTagActionSets.Add(result); } }