Esempio n. 1
0
        internal void UpdateCodeElementNodeKey(AbstractKeyedCodeElement keyedElement, SyntaxNodeKey oldNodeKey, SyntaxNodeKey newNodeKey)
        {
            if (!_codeElementTable.TryGetValue(oldNodeKey, out var codeElement))
            {
                throw new InvalidOperationException($"Could not find {oldNodeKey} in Code Model element table.");
            }

            _codeElementTable.Remove(oldNodeKey);

            var managedElement = ComAggregate.GetManagedObject <AbstractKeyedCodeElement>(codeElement);

            if (!object.Equals(managedElement, keyedElement))
            {
                throw new InvalidOperationException($"Unexpected failure in Code Model while updating node keys {oldNodeKey} -> {newNodeKey}");
            }

            // If we're updating this element with the same node key as an element that's already in the table,
            // just remove the old element. The old element will continue to function (through its node key), but
            // the new element will replace it in the cache.
            if (_codeElementTable.ContainsKey(newNodeKey))
            {
                _codeElementTable.Remove(newNodeKey);
            }

            _codeElementTable.Add(newNodeKey, codeElement);
        }
            public void Add(SyntaxNodeKey key, EnvDTE.CodeElement element)
            {
                // This code deals with a weird case of interaction with WinForms: The same
                // element can be added multiple times. What we have to do is bump
                // the conflicting element to a free [KeyName, Ordinal] slot
                // by incrementing [Ordinal]
                // Elements with the same node path can also be added multiple times in
                // normal editing scenarios, e.g. when a code element is changing preserving its name
                // (e.g. a class becomes an interface) or user just removes a block of code and
                // then readds it back before code elements for removed code were garbage collected.
                CodeElementWeakComAggregateHandle existingElementHandle;

                if (_elementWeakComHandles.TryGetValue(key, out existingElementHandle))
                {
                    int newOrdinal = key.Ordinal;
                    while (true)
                    {
                        newOrdinal++;
                        var currentKey = new SyntaxNodeKey(key.Name, newOrdinal);
                        if (!_elementWeakComHandles.ContainsKey(currentKey))
                        {
                            // We found a free "slot": use it and release the previous one
                            AbstractKeyedCodeElement existingElement = null;
                            EnvDTE.CodeElement       existingElementManagedObject;
                            if (existingElementHandle.TryGetManagedObjectWithoutCaringWhetherNativeObjectIsAlive(out existingElementManagedObject))
                            {
                                existingElement = existingElementManagedObject as AbstractKeyedCodeElement;
                            }

                            _elementWeakComHandles.Remove(key);

                            if (existingElementHandle.ComAggregateObject == null)
                            {
                                // The native object has already been released.
                                // There's no need to re-add this handle.
                                break;
                            }

                            Debug.Assert(existingElement != null, "The ComAggregate is alive. Why isn't the actual managed object?");

                            _elementWeakComHandles.Add(currentKey, existingElementHandle);
                            existingElement.NodeKey = currentKey;
                            break;
                        }
                    }
                }

                Debug.Assert(!_elementWeakComHandles.ContainsKey(key),
                             "All right, we got it wrong. We should ahve a free entry in the table!");

                _elementWeakComHandles.Add(key, new CodeElementWeakComAggregateHandle(element));
            }
Esempio n. 3
0
        internal void UpdateCodeElementNodeKey(AbstractKeyedCodeElement keyedElement, SyntaxNodeKey oldNodeKey, SyntaxNodeKey newNodeKey)
        {
            var codeElement = _codeElementTable.Remove(oldNodeKey);

            var managedElement = ComAggregate.GetManagedObject <AbstractKeyedCodeElement>(codeElement);

            if (!object.Equals(managedElement, keyedElement))
            {
                throw new InvalidOperationException($"Unexpected failure in Code Model while updating node keys {oldNodeKey} -> {newNodeKey}");
            }

            _codeElementTable.Add(newNodeKey, codeElement);
        }
Esempio n. 4
0
        /// <summary>
        /// This function re-adds a code element to the table, taking care not to duplicate
        /// an element (i.e., making sure that no two elements with the same key-ordinal
        /// appear in the same element chain in the table).  To resolve any conflict, each
        /// node with the given key is examined positionally, and the existing order is
        /// maintained as closely as possible -- but it is still possible the code element
        /// references to duplicate elements can get "bumped" by odd edits -- nothing we
        /// can do about this.
        /// </summary>
        internal void ResetElementNodeKey(AbstractKeyedCodeElement element, SyntaxNodeKey nodeKey)
        {
            EnvDTE.CodeElement elementInTable;
            _elementTable.Remove(element.NodeKey, out elementInTable);

            var abstractElementInTable = ComAggregate.GetManagedObject <AbstractKeyedCodeElement>(elementInTable);

            if (!object.Equals(abstractElementInTable, element))
            {
                Debug.Fail("Found a different element with the same key!");
                throw new InvalidOperationException();
            }

            abstractElementInTable.NodeKey = nodeKey;

            _elementTable.Add(nodeKey, elementInTable);
        }