static void RevaluatePropertyInheritanceAdornments(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 || !VSServiceProvider.IsModelReady(parseTree)) { @this._textViewTracker.IsLatestSourceFileStale = true; Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain); return; } //Collect all the properties in this text view var propertyCollector = new PropertyCollector(workingSnapshot); propertyCollector.Visit(parseTree.RootNode); var properties = propertyCollector.GetProperties(); //Get our property keys var keys = new List <object>(); var newTuples = new List <Tuple <object, object> >(); foreach (var tuple in properties.Keys) { if (tuple.Item1 != null) { keys.Add(tuple.Item1); } if (tuple.Item2 != null) { keys.Add(tuple.Item2); } if (!(@this._propertyKeys.Contains(tuple.Item1) && @this._propertyKeys.Contains(tuple.Item1))) { newTuples.Add(tuple); } } VSServiceProvider.Current.Logger.WriteToLog(String.Format("Found {0} new properties.", newTuples.Count)); //Update our property keys @this._propertyKeys.Clear(); @this._propertyKeys.AddAll(keys); VSServiceProvider.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) { VSServiceProvider.Current.Logger.WriteToLog("Unexpected: A key in the AdornmentManager wasn't a string! key: " + key.ToString()); continue; } if (!@this._propertyKeys.Contains(key) && keyAsString.EndsWith(PropertyCollector.PropertyTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); VSServiceProvider.Current.Logger.WriteToLog("Removing obsolete property adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new properties and queue them for contract lookup VSServiceProvider.Current.QueueWorkItem(() => { foreach (var tuple in newTuples) { PropertyDeclarationNode property; if (properties.TryGetValue(tuple, out property)) { if (tuple.Item1 != null && tuple.Item2 != null && property.GetAccessorDeclaration.GetSpan().Start.Line == property.SetAccessorDeclaration.GetSpan().Start.Line) { // set and get on same line, don't add adornment VSServiceProvider.Current.Logger.WriteToLog("Skipping adornments for " + property.GetName(workingSnapshot) + " because get and set are on same line"); } else { VSServiceProvider.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + property.GetName(workingSnapshot)); if (tuple.Item1 != null) { #region Create getter placeholder adornment VSServiceProvider.Current.Logger.WriteToLog(String.Format("\t(Creating getter placeholder with tag {0})", tuple.Item1)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.GetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); var ops = AdornmentOptionsHelper.GetAdornmentOptions(VSServiceProvider.Current.VSOptionsPage); @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, VSServiceProvider.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item1); #endregion } if (tuple.Item2 != null) { #region Create setter placeholder adornment VSServiceProvider.Current.Logger.WriteToLog(String.Format("\t(Creating setter placeholder with tag {0})", tuple.Item2)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.SetAccessorDeclaration.GetSpan().Convert(workingSnapshot).Start, 1); var trackingSpan = workingSnapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); var ops = AdornmentOptionsHelper.GetAdornmentOptions(VSServiceProvider.Current.VSOptionsPage); @this._adornmentManager.AddAdornment(new InheritanceContractAdornment(trackingSpan, @this._textViewTracker.VSTextProperties, VSServiceProvider.Current.Logger, @this._adornmentManager.QueueRefreshLineTransformer, ops), tuple.Item2); #endregion } @this._propertiesNeedingContractLookup.Enqueue(new KeyValuePair <Tuple <object, object>, PropertyDeclarationNode>(tuple, property)); } } } }); //Most likely we've changed something (and this is a pretty cheap call), so let's ask for a refresh Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(@this._adornmentManager.QueueRefreshLineTransformer, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts Utilities.Delay(() => VSServiceProvider.Current.QueueWorkItem(VSServiceProvider.Current.AskForNewVSModel, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); }
static void RevaluatePropertyInheritanceAdornments(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 properties in this text view var propertyCollector = new PropertyCollector(workingSnapshot); propertyCollector.Visit(parseTree.RootNode); var properties = propertyCollector.GetProperties(); //Get our property keys var keys = new List<object>(); var newTuples = new List<Tuple<object, object>>(); foreach (var tuple in properties.Keys) { if (tuple.Item1 != null) keys.Add(tuple.Item1); if (tuple.Item2 != null) keys.Add(tuple.Item2); if (!(@this._propertyKeys.Contains(tuple.Item1) && @this._propertyKeys.Contains(tuple.Item1))) newTuples.Add(tuple); } ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("Found {0} new properties.", newTuples.Count)); //Update our property keys @this._propertyKeys.Clear(); @this._propertyKeys.AddAll(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._propertyKeys.Contains(key) && keyAsString.EndsWith(PropertyCollector.PropertyTagSuffix)) { @this._adornmentManager.RemoveAdornment(key); ContractsPackageAccessor.Current.Logger.WriteToLog("Removing obsolete property adornment with tag: " + keyAsString); } } }, () => @this._textViewTracker.TextView.IsClosed || @this._textViewTracker.TextView.HasAggregateFocus); //Create placeholder adornments for our new properties and queue them for contract lookup ContractsPackageAccessor.Current.QueueWorkItem(() => { foreach (var tuple in newTuples) { PropertyDeclarationNode property; if (properties.TryGetValue(tuple, out property)) { if (tuple.Item1 != null && tuple.Item2 != null && property.GetAccessorDeclaration.GetSpan().Start.Line == property.SetAccessorDeclaration.GetSpan().Start.Line) { // set and get on same line, don't add adornment ContractsPackageAccessor.Current.Logger.WriteToLog("Skipping adornments for " + property.GetName(workingSnapshot) + " because get and set are on same line"); } else { ContractsPackageAccessor.Current.Logger.WriteToLog("Creating placeholder adornment and enqueueing for future contract lookup for: " + property.GetName(workingSnapshot)); if (tuple.Item1 != null) { #region Create getter placeholder adornment ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating getter placeholder with tag {0})", tuple.Item1)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.GetAccessorDeclaration.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), tuple.Item1); #endregion } if (tuple.Item2 != null) { #region Create setter placeholder adornment ContractsPackageAccessor.Current.Logger.WriteToLog(String.Format("\t(Creating setter placeholder with tag {0})", tuple.Item2)); //We add the placeholder adornment here because our workingSnapshot corresponds most closely to the syntactic model's text var snapshotSpan = new SnapshotSpan(property.SetAccessorDeclaration.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), tuple.Item2); #endregion } @this._propertiesNeedingContractLookup.Enqueue(new KeyValuePair<Tuple<object, object>, PropertyDeclarationNode>(tuple, property)); } } } }); //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, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); //Ask for the new VS model so we can look up contracts Utilities.Delay(() => ContractsPackageAccessor.Current.QueueWorkItem(ContractsPackageAccessor.Current.AskForNewVSModel, () => @this._textViewTracker.TextView.HasAggregateFocus), DelayAfterMembersRevalutation); }