1. 20 11月, 2015 1 次提交
  2. 31 10月, 2015 2 次提交
  3. 27 10月, 2015 5 次提交
  4. 16 10月, 2015 4 次提交
  5. 15 10月, 2015 4 次提交
  6. 12 10月, 2015 1 次提交
    • D
      Fix further issues with Code Model lifetime management · 4fd5d1b0
      Dustin Campbell 提交于
      Fixes #5868
      Fixes #5841
      
      * Added another "stress" test that performs 100 operations to catch failures in the element table.
      * Addressed problem where CleanableWeakComHandleTable.TryGetValue() might incorrectly return true.
      * Fixed issue in FileCodeModel.GetOrCreateCodeElement() where a node key might not be removed from the element table.
      * Unskip tests
      4fd5d1b0
  7. 11 10月, 2015 1 次提交
  8. 10 10月, 2015 7 次提交
  9. 09 10月, 2015 1 次提交
  10. 30 9月, 2015 2 次提交
  11. 29 9月, 2015 3 次提交
  12. 04 9月, 2015 3 次提交
  13. 05 8月, 2015 1 次提交
  14. 04 8月, 2015 1 次提交
  15. 07 7月, 2015 1 次提交
  16. 16 6月, 2015 1 次提交
  17. 10 6月, 2015 1 次提交
  18. 04 6月, 2015 1 次提交
    • D
      Code Model: Fix issue with parented code model objects corrupting their parents · 5870bc7f
      Dustin Campbell 提交于
      This is a fairly involved issue that can manifest in a number of ways.
      Currently, the only known scenario where this is exposed within VS is
      the "Convert to Web Application" command but there are certainly others
      and customers using Code Model could easily run into it.
      
      The scenario is essentially this:
      
      * In Code Model, grab and hold a reference to a code model object for
      some container element.
      * Access a certain type of child element parented by that container. In
      particular, a property accessor, an event accessor, an attribute, an
      attribute argument, a VB Inherits statement, a VB Implements statement,
      or using directive/Imports statement.
      * Try to access a property on the container reference in step 1.
      * Exception gets thrown!
      
      Understanding why this happens will require understanding a few of the
      system concepts underlying Code Model.
      
      First, Code Model elements tend to have long lifetimes that live through
      file edits and even renames. For example, one could grab a reference to
      an ```EnvDTE.CodeClass``` and hold onto it. As the user makes edits to
      the file containing that class the class element should continute to be
      valid (until the user makes an edit that breaks it). Since their
      lifetimes can be potentially long, Code Model elements hold onto "node
      keys" rather than the SyntaxTree nodes, which they use to get back to
      their underlying node in the source file.
      
      Node keys have a very simple format. Essentially, they are the "name" of
      the node (qualified syntactically) along with an ordinal which allows
      there to be multiple nodes with the same name. Consider the following
      code:
      
      ```C#
      namespace N
      {
      partial class C
      {
      void M() { }
      }
      
      partial class C
      {
      }
      }
      ```
      
      In the code above, there are four potential Code Model elements with the
      following node keys:
      
      * N, 1
      * N.C, 1
      * N.C.M, 1
      * N.C, 2
      
      Second, some Code Model elements don't actually have node keys. These
      are objects that are parented by other code model objects. For example,
      parameters are parented within a method or propery, property accessors
      are parented within a property, etc. These "keyless" objects can be a
      bit tricky because they need to hold a reference to their parent object.
      
      Third, each FileCodeModel maintains a cache of Code Model elements using
      their node keys. Whenever a Code Model element is going to be created
      for a particular node key, the FileCodeModel first checks to see an
      element already exists. If so, it returns the cached element instead.
      
      With that background, here's what's happening:
      
      In several cases, creating a parented keyless Code Model element was
      skipping the lookup in the FileCodeModel's cache when creating it's
      parent. So, if an element represent the parent already existed in the
      cache, a second Code Model element would be created for the same node.
      This gets ugly because the process creating a Code Model element causes
      it to be added to the FileCodeModel's cache. So, there is an attempt to
      add the newly created Code Model element when there's already one
      present in the cache with the same node key.
      
      Ideally, this situation would have thrown an exception. However, when
      there's a collision, there's a code path in the FileCodeModel's cache
      that tries to find a free slot in the cache by changing the original of
      the element's node key. This code is super-suspicious and is, quite
      honestly, probably wrong. However, removing it is a risky at this point.
      So, I'll look at cleaning this up in the master branch.
      
      For now, I've audited all of the places where a parented keyless Code
      Model element constructs its parent and ensures that it goes through the
      FileCodeModel's lookup.
      5870bc7f