Exemplo n.º 1
0
        static void RecursivelyLookupContractsForProperties(InheritanceTracker @this)
        {
            Contract.Requires(@this != null);

            #region Dequeue
            if (@this._propertiesNeedingContractLookup.Count < 1)
            {
                return;
            }
            var propertyPair = @this._propertiesNeedingContractLookup.Dequeue();
            var property     = propertyPair.Value;
            var tagTuple     = propertyPair.Key;
            #endregion
            try {
                var comp = @this._textViewTracker.LatestCompilation;
                if (comp == null)
                {
                    ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model.");
                    @this._textViewTracker.IsLatestCompilationStale = true;
                    Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
                    @this.semanticModelsFetchedCounter++;
                    goto RequeueAndAbort;
                }
                #region Get semantic property from syntactic property
                CSharpMember semanticProperty = null;
                semanticProperty = comp.GetMemberForPropertyDeclaration(property);
                if (semanticProperty == null)
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3)
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property, waiting for a new semantic model.");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property. Too many semantic models have already been fetched, skipping this property...");
                        goto Continue;
                    }
                }
                #endregion
                #region Try get the property that this property is inherited from
                CSharpMember inheritedFromProperty;
                if (!TryGetIheritedFromMember(semanticProperty, property.Parent as TypeDeclarationNode, out inheritedFromProperty))
                {
                    goto Continue;
                }
                #endregion
                #region Uninstantiated property
                semanticProperty = semanticProperty.Uninstantiate();
                #endregion
                #region Get our tool tip
                var toolTip = "";
                if (!semanticProperty.IsAbstract && !semanticProperty.ContainingType.IsInterface)
                {
                    toolTip = String.Format("Contracts inherited from {0}.", inheritedFromProperty.ContainingType.Name.Text);
                }
                #endregion
                #region Try get accessor contracts and update adornment
                IMethodReference getterReference = null;
                IMethodReference setterReference = null;
                if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyAccessorReferences(inheritedFromProperty, out getterReference, out setterReference))
                {
                    if (tagTuple.Item1 != null && getterReference != null)
                    {
                        IMethodContract getterContracts;
                        if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(getterReference, out getterContracts))
                        {
                            var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item1);
                            if (possibleAdornment != null)
                            {
                                var adornment = possibleAdornment as ContractAdornment;
                                if (adornment != null)
                                {
                                    adornment.SetContracts(getterContracts, toolTip);
                                }
                                else
                                {
                                    ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping getter...");
                                }
                            }
                            else
                            {
                                ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping getter...");
                            }
                        }
                    }
                    if (tagTuple.Item2 != null && setterReference != null)
                    {
                        IMethodContract setterContracts;
                        if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(setterReference, out setterContracts))
                        {
                            var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item2);
                            if (possibleAdornment != null)
                            {
                                var adornment = possibleAdornment as ContractAdornment;
                                if (adornment != null)
                                {
                                    adornment.SetContracts(setterContracts, toolTip);
                                }
                                else
                                {
                                    ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping setter...");
                                }
                            }
                            else
                            {
                                ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping setter...");
                            }
                        }
                    }
                }
                else
                {
                    ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + inheritedFromProperty.Name.Text);
                }
                #endregion
            }
            #region Exception handeling
            catch (IllFormedSemanticModelException e) {
                if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2)
                {
                    ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model...");
                    @this._textViewTracker.IsLatestCompilationStale = true;
                    ContractsPackageAccessor.Current.AskForNewVSModel();
                    @this.semanticModelsFetchedCounter++;
                    goto RequeueAndAbort;
                }
                else
                {
                    ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this property...");
                    goto Continue;
                }
            } catch (InvalidOperationException e) {
                if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate))
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5)
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        ContractsPackageAccessor.Current.AskForNewVSModel();
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property...");
                        goto Continue;
                    }
                }
                else
                {
                    throw e;
                }
            } catch (COMException e) {
                if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed))
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5)
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        ContractsPackageAccessor.Current.AskForNewVSModel();
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property...");
                        goto Continue;
                    }
                }
                else
                {
                    throw e;
                }
            }
            #endregion
Continue:
            ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(@this));
            return;

RequeueAndAbort:
            @this._propertiesNeedingContractLookup.Enqueue(propertyPair);
            return;
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
        static void RecursivelyLookupContractsForMethods(InheritanceTracker @this)
        {
            Contract.Requires(@this != null);

            #region Dequeue
            if (@this._methodsNeedingContractLookup.Count < 1)
            {
                return;
            }
            var methodPair = @this._methodsNeedingContractLookup.Dequeue();
            var method     = methodPair.Value;
            var tag        = methodPair.Key;
            #endregion
            try {
                VSServiceProvider.Current.Logger.WriteToLog(String.Format("Attempting to lookup contracts for '{0}'", tag.ToString()));
                var comp = @this._textViewTracker.LatestCompilation;
                if (comp == null)
                {
                    VSServiceProvider.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model.");
                    @this._textViewTracker.IsLatestCompilationStale = true;
                    Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
                    @this.semanticModelsFetchedCounter++;
                    goto RequeueAndAbort;
                }
                #region Get semantic method from syntactic method
                CSharpMember semanticMethod = null;
                semanticMethod = comp.GetMemberForMethodDeclaration(method);
                if (semanticMethod == null)
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3)
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method, waiting for a new semantic model.");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method. Too many semantic models have already been fetched, skipping this method...");
                        goto Continue;
                    }
                }
                #endregion
                #region Try get the method that this method is inherited from
                CSharpMember inheritedFromMethod;
                if (!TryGetIheritedFromMember(semanticMethod, method.Parent as TypeDeclarationNode, out inheritedFromMethod))
                {
                    goto Continue;
                }
                #endregion
                #region Uninstantiated method
                semanticMethod = semanticMethod.Uninstantiate();
                #endregion
                #region Get our tool tip
                var toolTip = "";
                if (!semanticMethod.IsAbstract && !semanticMethod.ContainingType.IsInterface)
                {
                    toolTip = String.Format("Contracts inherited from {0}.", inheritedFromMethod.ContainingType.Name.Text);
                }
                #endregion
                #region Try get method contracts and update adornment
                IMethodContract contracts = null;
                if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(inheritedFromMethod, out contracts))
                {
                    var possibleAdornment = @this._adornmentManager.GetAdornment(tag);
                    if (possibleAdornment != null)
                    {
                        var adornment = possibleAdornment as ContractAdornment;
                        if (adornment != null)
                        {
                            adornment.SetContracts(contracts, toolTip);
                        }
                        else
                        {
                            VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping method...");
                        }
                    }
                    else
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment not found, skipping method...");
                    }
                }
                #endregion
            }
            #region Exception handeling
            catch (IllFormedSemanticModelException e) {
                if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2)
                {
                    VSServiceProvider.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model...");
                    @this._textViewTracker.IsLatestCompilationStale = true;
                    VSServiceProvider.Current.AskForNewVSModel();
                    @this.semanticModelsFetchedCounter++;
                    goto RequeueAndAbort;
                }
                else
                {
                    VSServiceProvider.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this method...");
                    goto Continue;
                }
            } catch (InvalidOperationException e) {
                if (e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate))
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5)
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        VSServiceProvider.Current.AskForNewVSModel();
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method...");
                        goto Continue;
                    }
                }
                else
                {
                    throw e;
                }
            } catch (COMException e) {
                if (e.Message.Contains(VSServiceProvider.COMExceptionMessage_BindingFailed))
                {
                    if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5)
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
                        @this._textViewTracker.IsLatestCompilationStale = true;
                        VSServiceProvider.Current.AskForNewVSModel();
                        @this.semanticModelsFetchedCounter++;
                        goto RequeueAndAbort;
                    }
                    else
                    {
                        VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method...");
                        goto Continue;
                    }
                }
                else
                {
                    throw e;
                }
            }
            #endregion
Continue:
            VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(@this));
            return;

RequeueAndAbort:
            @this._methodsNeedingContractLookup.Enqueue(methodPair);
            return;
        }
    static void RecursivelyLookupContractsForProperties(InheritanceTracker @this) {
      Contract.Requires(@this != null);

      #region Dequeue
      if (@this._propertiesNeedingContractLookup.Count < 1)
        return;
      var propertyPair = @this._propertiesNeedingContractLookup.Dequeue();
      var property = propertyPair.Value;
      var tagTuple = propertyPair.Key;
      #endregion
      try {
        var comp = @this._textViewTracker.LatestCompilation;
        if (comp == null) {
          ContractsPackageAccessor.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model.");
          @this._textViewTracker.IsLatestCompilationStale = true;
          Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
          @this.semanticModelsFetchedCounter++;
          goto RequeueAndAbort;
        }
        #region Get semantic property from syntactic property
        CSharpMember semanticProperty = null;
        semanticProperty = comp.GetMemberForPropertyDeclaration(property);
        if (semanticProperty == null) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) {
            ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property, waiting for a new semantic model.");
            @this._textViewTracker.IsLatestCompilationStale = true;
            Utilities.Delay(() => ContractsPackageAccessor.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get semantic property from syntactic property. Too many semantic models have already been fetched, skipping this property...");
            goto Continue;
          }
        }
        #endregion
        #region Try get the property that this property is inherited from
        CSharpMember inheritedFromProperty;
        if (!TryGetIheritedFromMember(semanticProperty, property.Parent as TypeDeclarationNode, out inheritedFromProperty)) {
          goto Continue;
        }
        #endregion
        #region Uninstantiated property
        semanticProperty = semanticProperty.Uninstantiate();
        #endregion
        #region Get our tool tip
        var toolTip = "";
        if (!semanticProperty.IsAbstract && !semanticProperty.ContainingType.IsInterface)
          toolTip = String.Format("Contracts inherited from {0}.", inheritedFromProperty.ContainingType.Name.Text);
        #endregion
        #region Try get accessor contracts and update adornment
        IMethodReference getterReference = null;
        IMethodReference setterReference = null;
        if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetPropertyAccessorReferences(inheritedFromProperty, out getterReference, out setterReference)) {
          if (tagTuple.Item1 != null && getterReference != null) {
            IMethodContract getterContracts;
            if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(getterReference, out getterContracts)) {
              var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item1);
              if (possibleAdornment != null) {
                var adornment = possibleAdornment as ContractAdornment;
                if (adornment != null) {
                  adornment.SetContracts(getterContracts, toolTip);
                } else {
                  ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping getter...");
                }
              } else {
                ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping getter...");
              }
            }
          }
          if (tagTuple.Item2 != null && setterReference != null) {
            IMethodContract setterContracts;
            if (((ContractsProvider)@this._textViewTracker.ProjectTracker.ContractsProvider).TryGetMethodContract(setterReference, out setterContracts)) {
              var possibleAdornment = @this._adornmentManager.GetAdornment(tagTuple.Item2);
              if (possibleAdornment != null) {
                var adornment = possibleAdornment as ContractAdornment;
                if (adornment != null) {
                  adornment.SetContracts(setterContracts, toolTip);
                } else {
                  ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping setter...");
                }
              } else {
                ContractsPackageAccessor.Current.Logger.WriteToLog("Placeholder adornment not found, skipping setter...");
              }
            }
          }
        } else {
          ContractsPackageAccessor.Current.Logger.WriteToLog("Failed to get CCI reference for: " + inheritedFromProperty.Name.Text);
        }
        #endregion
      }
      #region Exception handeling
 catch (IllFormedSemanticModelException e) {
        if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) {
          ContractsPackageAccessor.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model...");
          @this._textViewTracker.IsLatestCompilationStale = true;
          ContractsPackageAccessor.Current.AskForNewVSModel();
          @this.semanticModelsFetchedCounter++;
          goto RequeueAndAbort;
        } else {
          ContractsPackageAccessor.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this property...");
          goto Continue;
        }
      } catch (InvalidOperationException e) {
        if (e.Message.Contains(ContractsPackageAccessor.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) {
            ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
            @this._textViewTracker.IsLatestCompilationStale = true;
            ContractsPackageAccessor.Current.AskForNewVSModel();
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property...");
            goto Continue;
          }
        } else
          throw e;
      } catch (COMException e) {
        if (e.Message.Contains(ContractsPackageAccessor.COMExceptionMessage_BindingFailed)) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) {
            ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
            @this._textViewTracker.IsLatestCompilationStale = true;
            ContractsPackageAccessor.Current.AskForNewVSModel();
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            ContractsPackageAccessor.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this property...");
            goto Continue;
          }
        } else
          throw e;
      }
      #endregion
    Continue:
      ContractsPackageAccessor.Current.QueueWorkItem(() => RecursivelyLookupContractsForProperties(@this));
      return;
    RequeueAndAbort:
      @this._propertiesNeedingContractLookup.Enqueue(propertyPair);
      return;
    }
    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);
    }
    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);
    }
Exemplo n.º 8
0
    static void RecursivelyLookupContractsForMethods(InheritanceTracker @this) {
      Contract.Requires(@this != null);

      #region Dequeue
      if (@this._methodsNeedingContractLookup.Count < 1)
        return;
      var methodPair = @this._methodsNeedingContractLookup.Dequeue();
      var method = methodPair.Value;
      var tag = methodPair.Key;
      #endregion
      try {
        VSServiceProvider.Current.Logger.WriteToLog(String.Format("Attempting to lookup contracts for '{0}'", tag.ToString()));
        var comp = @this._textViewTracker.LatestCompilation;
        if (comp == null) {
          VSServiceProvider.Current.Logger.WriteToLog("No LatestCompilation, waiting for a new semantic model.");
          @this._textViewTracker.IsLatestCompilationStale = true;
          Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
          @this.semanticModelsFetchedCounter++;
          goto RequeueAndAbort;
        }
        #region Get semantic method from syntactic method
        CSharpMember semanticMethod = null;
        semanticMethod = comp.GetMemberForMethodDeclaration(method);
        if (semanticMethod == null) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 3) {
            VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method, waiting for a new semantic model.");
            @this._textViewTracker.IsLatestCompilationStale = true;
            Utilities.Delay(() => VSServiceProvider.Current.AskForNewVSModel(), DelayOnVSModelFailedBeforeTryingAgain);
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            VSServiceProvider.Current.Logger.WriteToLog("Failed to get semantic method from syntactic method. Too many semantic models have already been fetched, skipping this method...");
            goto Continue;
          }
        }
        #endregion
        #region Try get the method that this method is inherited from
        CSharpMember inheritedFromMethod;
        if (!TryGetIheritedFromMember(semanticMethod, method.Parent as TypeDeclarationNode, out inheritedFromMethod)) {
          goto Continue;
        }
        #endregion
        #region Uninstantiated method
        semanticMethod = semanticMethod.Uninstantiate();
        #endregion
        #region Get our tool tip
        var toolTip = "";
        if (!semanticMethod.IsAbstract && !semanticMethod.ContainingType.IsInterface)
          toolTip = String.Format("Contracts inherited from {0}.", inheritedFromMethod.ContainingType.Name.Text);
        #endregion
        #region Try get method contracts and update adornment
        IMethodContract contracts = null;
        if (@this._textViewTracker.ProjectTracker.ContractsProvider.TryGetMethodContract(inheritedFromMethod, out contracts)) {
          var possibleAdornment = @this._adornmentManager.GetAdornment(tag);
          if (possibleAdornment != null) {
            var adornment = possibleAdornment as ContractAdornment;
            if (adornment != null) {
              adornment.SetContracts(contracts, toolTip);
            } else {
              VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment isn't a ContractAdornment (not good!), skipping method...");
            }
          } else {
            VSServiceProvider.Current.Logger.WriteToLog("Placeholder adornment not found, skipping method...");
          }
        }
        #endregion
      }
      #region Exception handeling
 catch (IllFormedSemanticModelException e) {
        if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 2) {
          VSServiceProvider.Current.Logger.WriteToLog("Error: An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Asking for a new semantic model...");
          @this._textViewTracker.IsLatestCompilationStale = true;
          VSServiceProvider.Current.AskForNewVSModel();
          @this.semanticModelsFetchedCounter++;
          goto RequeueAndAbort;
        } else {
          VSServiceProvider.Current.Logger.WriteToLog("An 'IllFormedSemanticModelException' occured: '" + e.Message + "' Too many semantic models have been fetched, skipping this method...");
          goto Continue;
        }
      } catch (InvalidOperationException e) {
        if (e.Message.Contains(VSServiceProvider.InvalidOperationExceptionMessage_TheSnapshotIsOutOfDate)) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) {
            VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
            @this._textViewTracker.IsLatestCompilationStale = true;
            VSServiceProvider.Current.AskForNewVSModel();
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method...");
            goto Continue;
          }
        } else
          throw e;
      } catch (COMException e) {
        if (e.Message.Contains(VSServiceProvider.COMExceptionMessage_BindingFailed)) {
          if (@this.trackingNumberOfFetchedSemanticModels && @this.semanticModelsFetchedCounter <= 5) {
            VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts, getting new compilation...");
            @this._textViewTracker.IsLatestCompilationStale = true;
            VSServiceProvider.Current.AskForNewVSModel();
            @this.semanticModelsFetchedCounter++;
            goto RequeueAndAbort;
          } else {
            VSServiceProvider.Current.Logger.WriteToLog("The Visual Studio Semantic/Syntactic model threw an exception (it's snapshot is out of date) while looking up contracts. Too many compilations have already been fetched, skipping this method...");
            goto Continue;
          }
        } else
          throw e;
      }
      #endregion
    Continue:
      VSServiceProvider.Current.QueueWorkItem(() => RecursivelyLookupContractsForMethods(@this));
      return;
    RequeueAndAbort:
      @this._methodsNeedingContractLookup.Enqueue(methodPair);
      return;
    }