static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { Contract.Requires(@this != null); var workingSnapshot = @this._textViewTracker.TextView.TextSnapshot; //Save the current snapshot so it doesn't change while you work, we assume that the snapshot is the same as the source file. //Check if model is ready var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); if (parseTree == null || !parseTree.IsModelReady()) { @this._textViewTracker.IsLatestSourceFileStale = true; Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); return; } //Collect all the methods in this text view var methodCollector = new MethodCollector(workingSnapshot); methodCollector.Visit(parseTree.RootNode); var methods = methodCollector.GetMethods(); //Calculate which methods are new var newKeys = new List <object>(methods.Keys.Where((k) => !@this._methodKeys.Contains(k))); ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new methods.", newKeys.Count)); //Update our method keys @this._methodKeys.Clear(); @this._methodKeys.AddAll(methods.Keys); ContractsPackageAccessor.Current.QueueWorkItem(() => { if (@this._textViewTracker.TextView.IsClosed) { return; } var adornmentKeys = new List <object>(@this._adornmentManager.Adornments.Keys); foreach (var key in adornmentKeys) { var keyAsString = key as string; if (keyAsString == null) { ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); continue; } if (!@this._methodKeys.Contains(key) && keyAsString.EndsWith(MethodCollector.MethodTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete method adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new methods and queue them for contract lookup ContractsPackageAccessor.Current.QueueWorkItem(() => { foreach (var key in newKeys) { MethodDeclarationNode method; if (methods.TryGetValue(key, out method)) { ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + key.ToString()); #region Create placeholder adornment //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(method.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), key); #endregion @this._methodsNeedingContractLookup.Enqueue(new KeyValuePair <object, MethodDeclarationNode>(key, method)); } } }); //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel), DelayAfterMembersRevalutation); }
static void RevaluateMethodInheritanceAdornments(InheritanceTracker @this) { Contract.Requires(@this != null); var workingSnapshot = @this._textViewTracker.TextView.TextSnapshot; //Save the current snapshot so it doesn't change while you work, we assume that the snapshot is the same as the source file. //Check if model is ready var parseTree = @this._textViewTracker.LatestSourceFile == null ? null : @this._textViewTracker.LatestSourceFile.GetParseTree(); if (parseTree == null || !parseTree.IsModelReady()) { @this._textViewTracker.IsLatestSourceFileStale = true; Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); return; } //Collect all the methods in this text view var methodCollector = new MethodCollector(workingSnapshot); methodCollector.Visit(parseTree.RootNode); var methods = methodCollector.GetMethods(); //Calculate which methods are new var newKeys = new List<object>(methods.Keys.Where((k) => !@this._methodKeys.Contains(k))); ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new methods.", newKeys.Count)); //Update our method keys @this._methodKeys.Clear(); @this._methodKeys.AddAll(methods.Keys); ContractsPackageAccessor.Current.QueueWorkItem(() => { if (@this._textViewTracker.TextView.IsClosed) return; var adornmentKeys = new List<object>(@this._adornmentManager.Adornments.Keys); foreach (var key in adornmentKeys) { var keyAsString = key as string; if (keyAsString == null) { ContractsPackageAccessor.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); continue; } if (!@this._methodKeys.Contains(key) && keyAsString.EndsWith(MethodCollector.MethodTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete method adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new methods and queue them for contract lookup ContractsPackageAccessor.Current.QueueWorkItem(() => { foreach (var key in newKeys) { MethodDeclarationNode method; if (methods.TryGetValue(key, out method)) { ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + key.ToString()); #region Create placeholder adornment //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(method.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); var ops = AdornmentOptionsHelper.GetAdornmentOptions(ContractsPackageAccessor.Current.VSOptionsPage); @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, ContractsPackageAccessor.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), key); #endregion @this._methodsNeedingContractLookup.Enqueue(new KeyValuePair<object, MethodDeclarationNode>(key, method)); } } }); //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel), DelayAfterMembersRevalutation); }