internal static List<VsObjectSearchResult> Search(string name, ObjectSearchLanguage searchLanguage)
        {
            var results = new List<VsObjectSearchResult>();
            var searchService = PackageManager.Package.GetService(typeof(SVsObjectSearch)) as IVsObjectSearch;

            if (searchService != null)
            {
                IVsObjectList2 objectList;
                IVsObjectList searchResult;
                var criteria = new VSOBSEARCHCRITERIA();
                criteria.eSrchType = VSOBSEARCHTYPE.SO_ENTIREWORD;
                criteria.szName = name;

                // Need to switch between case sensitive and case insentive searches for C# and VB
                switch (searchLanguage)
                {
                    case ObjectSearchLanguage.CSharp:
                        criteria.grfOptions = (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS | (uint)_VSOBSEARCHOPTIONS.VSOBSO_CASESENSITIVE;
                        break;
                    case ObjectSearchLanguage.VB:
                        criteria.grfOptions = (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS;
                        break;
                    default:
                        throw new InvalidOperationException("Unsupported language search type: " + searchLanguage.ToString());
                }

                if (searchService.Find(
                    (uint)__VSOBSEARCHFLAGS.VSOSF_NOSHOWUI | (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS,
                    new VSOBSEARCHCRITERIA[1] { criteria }, out searchResult) == VSConstants.S_OK)
                {
                    objectList = searchResult as IVsObjectList2;
                    if (objectList != null)
                    {
                        uint pCount;
                        if (objectList.GetItemCount(out pCount) == VSConstants.S_OK)
                        {
                            for (uint i = 0; i < pCount; i++)
                            {
                                IVsObjectList2 subList;
                                if (objectList.GetList2(
                                    i, (uint)_LIB_LISTTYPE.LLT_HIERARCHY, (uint)_LIB_LISTFLAGS.LLF_NONE, new VSOBSEARCHCRITERIA2[0],
                                    out subList)
                                    == VSConstants.S_OK)
                                {
                                    // Switch to using our "safe" PInvoke interface for IVsObjectList2 to avoid potential memory management issues
                                    // when receiving strings as out params.
                                    var safeSubList = subList as ISafeVsObjectList2;
                                    if (safeSubList != null)
                                    {
                                        AddResultsToList(safeSubList, searchLanguage, results);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return results;
        }
Esempio n. 2
0
        internal static bool TryParseSourceData(
            string text, ObjectSearchLanguage searchLanguage, out string fileName, out int lineNumber, out int columnNumber)
        {
            switch (searchLanguage)
            {
            case ObjectSearchLanguage.CSharp:
                return(TryParseSourceDataCSharp(text, out fileName, out lineNumber, out columnNumber));

            case ObjectSearchLanguage.VB:
                return(TryParseSourceDataVB(text, out fileName, out lineNumber, out columnNumber));

            default:
                throw new InvalidOperationException("Unsupported language search type: " + searchLanguage.ToString());
            }
        }
Esempio n. 3
0
        private static void AddResultsToList(
            ISafeVsObjectList2 objectList, ObjectSearchLanguage searchLanguage, List <VsObjectSearchResult> results)
        {
            uint objectCount;

            if (objectList.GetItemCount(out objectCount) == VSConstants.S_OK)
            {
                for (uint j = 0; j < objectCount; j++)
                {
                    var textPointer = IntPtr.Zero;

                    try
                    {
                        if (objectList.GetText(j, VSTREETEXTOPTIONS.TTO_DEFAULT, out textPointer) == VSConstants.S_OK)
                        {
                            var text = Marshal.PtrToStringUni(textPointer);

                            if (text != null)
                            {
                                string fileName;
                                int    lineNumber;
                                int    columnNumber;

                                // FindAllReferencesList.cs (VS) does not implement the GetSourceContext() API of IVsObjectList2, so as a
                                // workaround we will parse the description text to identify the file and line/col number.
                                if (TryParseSourceData(text, searchLanguage, out fileName, out lineNumber, out columnNumber))
                                {
                                    results.Add(new VsObjectSearchResult(fileName, text, lineNumber, columnNumber));
                                }
                            }
                        }
                    }
                    finally
                    {
                        // If this object implements IVsCoTaskMemFreeMyStrings we *must* free the IntPtr since we were passed a copy
                        // of the string the native code is using. If the object does not implement IVsCoTaskMemFreeMyStrings we
                        //  *must not* free the IntPtr since we are referencing the same string the native code is using.
                        if (textPointer != IntPtr.Zero &&
                            objectList is IVsCoTaskMemFreeMyStrings)
                        {
                            Marshal.FreeCoTaskMem(textPointer);
                        }
                    }
                }
            }
        }
Esempio n. 4
0
        internal static List <VsObjectSearchResult> Search(string name, ObjectSearchLanguage searchLanguage)
        {
            var results       = new List <VsObjectSearchResult>();
            var searchService = PackageManager.Package.GetService(typeof(SVsObjectSearch)) as IVsObjectSearch;

            if (searchService != null)
            {
                IVsObjectList2 objectList;
                IVsObjectList  searchResult;
                var            criteria = new VSOBSEARCHCRITERIA();
                criteria.eSrchType = VSOBSEARCHTYPE.SO_ENTIREWORD;
                criteria.szName    = name;

                // Need to switch between case sensitive and case insentive searches for C# and VB
                switch (searchLanguage)
                {
                case ObjectSearchLanguage.CSharp:
                    criteria.grfOptions = (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS | (uint)_VSOBSEARCHOPTIONS.VSOBSO_CASESENSITIVE;
                    break;

                case ObjectSearchLanguage.VB:
                    criteria.grfOptions = (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS;
                    break;

                default:
                    throw new InvalidOperationException("Unsupported language search type: " + searchLanguage.ToString());
                }

                if (searchService.Find(
                        (uint)__VSOBSEARCHFLAGS.VSOSF_NOSHOWUI | (uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS,
                        new VSOBSEARCHCRITERIA[1] {
                    criteria
                }, out searchResult) == VSConstants.S_OK)
                {
                    objectList = searchResult as IVsObjectList2;
                    if (objectList != null)
                    {
                        uint pCount;
                        if (objectList.GetItemCount(out pCount) == VSConstants.S_OK)
                        {
                            for (uint i = 0; i < pCount; i++)
                            {
                                IVsObjectList2 subList;
                                if (objectList.GetList2(
                                        i, (uint)_LIB_LISTTYPE.LLT_HIERARCHY, (uint)_LIB_LISTFLAGS.LLF_NONE, new VSOBSEARCHCRITERIA2[0],
                                        out subList)
                                    == VSConstants.S_OK)
                                {
                                    // Switch to using our "safe" PInvoke interface for IVsObjectList2 to avoid potential memory management issues
                                    // when receiving strings as out params.
                                    var safeSubList = subList as ISafeVsObjectList2;
                                    if (safeSubList != null)
                                    {
                                        AddResultsToList(safeSubList, searchLanguage, results);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(results);
        }
        private static void AddResultsToList(
            ISafeVsObjectList2 objectList, ObjectSearchLanguage searchLanguage, List<VsObjectSearchResult> results)
        {
            uint objectCount;
            if (objectList.GetItemCount(out objectCount) == VSConstants.S_OK)
            {
                for (uint j = 0; j < objectCount; j++)
                {
                    var textPointer = IntPtr.Zero;

                    try
                    {
                        if (objectList.GetText(j, VSTREETEXTOPTIONS.TTO_DEFAULT, out textPointer) == VSConstants.S_OK)
                        {
                            var text = Marshal.PtrToStringUni(textPointer);

                            if (text != null)
                            {
                                string fileName;
                                int lineNumber;
                                int columnNumber;

                                // FindAllReferencesList.cs (VS) does not implement the GetSourceContext() API of IVsObjectList2, so as a
                                // workaround we will parse the description text to identify the file and line/col number.
                                if (TryParseSourceData(text, searchLanguage, out fileName, out lineNumber, out columnNumber))
                                {
                                    results.Add(new VsObjectSearchResult(fileName, text, lineNumber, columnNumber));
                                }
                            }
                        }
                    }
                    finally
                    {
                        // If this object implements IVsCoTaskMemFreeMyStrings we *must* free the IntPtr since we were passed a copy
                        // of the string the native code is using. If the object does not implement IVsCoTaskMemFreeMyStrings we
                        //  *must not* free the IntPtr since we are referencing the same string the native code is using.
                        if (textPointer != IntPtr.Zero
                            && objectList is IVsCoTaskMemFreeMyStrings)
                        {
                            Marshal.FreeCoTaskMem(textPointer);
                        }
                    }
                }
            }
        }
 internal static bool TryParseSourceData(
     string text, ObjectSearchLanguage searchLanguage, out string fileName, out int lineNumber, out int columnNumber)
 {
     switch (searchLanguage)
     {
         case ObjectSearchLanguage.CSharp:
             return TryParseSourceDataCSharp(text, out fileName, out lineNumber, out columnNumber);
         case ObjectSearchLanguage.VB:
             return TryParseSourceDataVB(text, out fileName, out lineNumber, out columnNumber);
         default:
             throw new InvalidOperationException("Unsupported language search type: " + searchLanguage.ToString());
     }
 }
Esempio n. 7
0
        internal static void CreateChangeProposals(CodeElement2 codeElement, string newName, string oldName,
                                                   string generatedItemPath, IList <ChangeProposal> changeProposals, ObjectSearchLanguage objectSearchLanguage)
        {
            if (codeElement != null)
            {
                var searchResults = VsObjectSearchResult.Search(codeElement.FullName, objectSearchLanguage);

                if (searchResults != null)
                {
                    // VB search results don't include the designer file, since the IVsObjectList item for the designer file in VB does not contain the
                    // column number for designer file references (since VB returns a hierarchical IVsObjectList and does not show column numbers in the
                    // root nodes). So instead we'll put the info from the CodeElement into the search results, which is less
                    // than ideal since the display text is not consistent with the IVsObjectList items...
                    if (objectSearchLanguage == ObjectSearchLanguage.VB &&
                        codeElement.ProjectItem != null)
                    {
                        searchResults.Add(CreateVBCodeElementSearchResult(codeElement));
                    }

                    if (searchResults.Count > 0)
                    {
                        var fileToChanges       = new Dictionary <string, List <RefactorChange> >();
                        var designerFileChanges = new List <RefactorChange>();

                        foreach (var searchResult in searchResults)
                        {
                            // Don't show changes in generated file in the preview dialog since those changes will always be applied after
                            // hydration completes. Instead we just show the changes from the exercising (application) code.
                            if (!string.Equals(searchResult.FileName, generatedItemPath, StringComparison.OrdinalIgnoreCase))
                            {
                                List <RefactorChange> refactorChanges;
                                if (!fileToChanges.TryGetValue(searchResult.FileName, out refactorChanges))
                                {
                                    refactorChanges = new List <RefactorChange>();
                                    fileToChanges.Add(searchResult.FileName, refactorChanges);
                                }

                                refactorChanges.Add(
                                    new RefactorChange(
                                        searchResult.DisplayText, searchResult.DisplayText, searchResult.LineNumber,
                                        searchResult.ColumnNumber));
                            }
                            else
                            {
                                // We need to know the location of the type definition in the generated code file so we can populate the
                                // root node of the preview window, so we save off a list of all references to the renamed object in
                                // the designer file here.
                                designerFileChanges.Add(
                                    new RefactorChange(
                                        searchResult.DisplayText, searchResult.DisplayText, searchResult.LineNumber,
                                        searchResult.ColumnNumber));
                            }
                        }

                        // Add designer file change
                        var  rootFileName = codeElement.ProjectItem.get_FileNames(1);
                        bool doesProjectHaveFileName;
                        var  rootProjectName = VsUtils.GetProjectPathWithName(
                            codeElement.ProjectItem.ContainingProject, out doesProjectHaveFileName);

                        // The code element start line will include attributes for the class, so the get the line where the actual class name is
                        // we need to use the results from the IVsObjectSearch and get the search result immediately after the CodeElements startline.
                        var            minDelta       = int.MaxValue;
                        RefactorChange?rootNodeChange = null;
                        foreach (var change in designerFileChanges)
                        {
                            var lineDelta = change.LineNumber - codeElement.StartPoint.Line;

                            if (lineDelta >= 0 &&
                                lineDelta < minDelta)
                            {
                                minDelta       = lineDelta;
                                rootNodeChange = change;
                            }
                        }

                        if (rootNodeChange != null)
                        {
                            var textChangeProposal = new VsLangTextChangeProposal(
                                rootProjectName, rootFileName, newName, codeElement.FullName, true);
                            textChangeProposal.StartColumn = rootNodeChange.Value.ColumnNumber - 1;
                            textChangeProposal.EndColumn   = textChangeProposal.StartColumn + oldName.Length;
                            textChangeProposal.Length      = oldName.Length;
                            textChangeProposal.StartLine   = rootNodeChange.Value.LineNumber - 1;
                            textChangeProposal.EndLine     = textChangeProposal.StartLine;
                            textChangeProposal.Included    = true;
                            changeProposals.Add(textChangeProposal);
                        }

                        // Add application code changes
                        foreach (var fileName in fileToChanges.Keys)
                        {
                            var owningProject = VSHelpers.GetProjectForDocument(fileName);
                            var changes       = fileToChanges[fileName];

                            if (changes.Count > 0 &&
                                owningProject != null)
                            {
                                foreach (var change in changes)
                                {
                                    // Text buffer is zero based but find all refs is one based, so subtract 1.
                                    var textBufferLine   = change.LineNumber - 1;
                                    var textBufferColumn = change.ColumnNumber - 1;

                                    bool projectHasFilename;
                                    var  projectFullPath    = VsUtils.GetProjectPathWithName(owningProject, out projectHasFilename);
                                    var  textChangeProposal = new VsLangTextChangeProposal(
                                        projectFullPath, fileName, newName, codeElement.FullName);
                                    textChangeProposal.StartColumn = textBufferColumn;
                                    textChangeProposal.EndColumn   = textChangeProposal.StartColumn + oldName.Length;
                                    textChangeProposal.Length      = oldName.Length;
                                    textChangeProposal.StartLine   = textBufferLine;
                                    textChangeProposal.EndLine     = textBufferLine;
                                    textChangeProposal.Included    = true;
                                    changeProposals.Add(textChangeProposal);
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 8
0
        internal static void FindRootCodeElementsToRename(
            IEnumerable <CodeElement2> codeElements,
            CodeElementRenameData renameData,
            string generatedItemPath,
            ObjectSearchLanguage objectSearchLanguage,
            ref Dictionary <CodeElement2, Tuple <string, string> > codeElementsToRename)
        {
            if (codeElementsToRename == null)
            {
                codeElementsToRename = new Dictionary <CodeElement2, Tuple <string, string> >();
            }

            var newName    = renameData.NewName;
            var oldName    = renameData.OldName;
            var targetType = renameData.RefactorTargetType;

            // Rename the symbols that match the old name
            foreach (var codeElement in codeElements)
            {
                if (codeElement.Kind == vsCMElement.vsCMElementNamespace)
                {
                    FindRootCodeElementsToRename(
                        codeElement.Children.OfType <CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                        ref codeElementsToRename);
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementClass)
                {
                    if (targetType == RefactorTargetType.Class)
                    {
                        if (codeElement.Name.Equals(oldName, StringComparison.Ordinal))
                        {
                            codeElementsToRename.Add(codeElement, new Tuple <string, string>(newName, oldName));
                        }

                        // If we're refactoring a class, we need to iterate another level deeper even if the name of this Type doesn't match what we're refactoring
                        // since we need to rename the AddTo*() functions
                        FindRootCodeElementsToRename(
                            codeElement.Children.OfType <CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                            ref codeElementsToRename);
                    }
                    else if (targetType == RefactorTargetType.Property)
                    {
                        // If we're refactoring a property we need to iterate another level deeper to find the property elements.
                        FindRootCodeElementsToRename(
                            codeElement.Children.OfType <CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                            ref codeElementsToRename);
                    }
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementFunction &&
                         targetType == RefactorTargetType.Class)
                {
                    // Functions use the entity set name, so check for pluralization
                    string oldFuncName;
                    string newFuncName;

                    var function           = (CodeFunction)codeElement;
                    var parentType         = function.Parent as CodeType;
                    var oldFactoryFuncName = string.Format(CultureInfo.InvariantCulture, CreateFuncFormat, oldName);
                    if (parentType != null &&
                        parentType.Name.Equals(oldName, StringComparison.Ordinal) &&
                        function.Name.Equals(oldFactoryFuncName, StringComparison.Ordinal))
                    {
                        // We need to rename Create* factory funcs as they use the class name.
                        codeElementsToRename.Add(
                            codeElement,
                            new Tuple <string, string>(
                                string.Format(CultureInfo.InvariantCulture, CreateFuncFormat, newName), oldFactoryFuncName));
                    }
                    else
                    {
                        // We also need to rename the AddTo* funcs when we rename classes, since the class name is used in the generated func name.
                        oldFuncName = string.Format(CultureInfo.InvariantCulture, AddToFuncFormat, renameData.OldEntitySetName);

                        if (codeElement.Name.Equals(oldFuncName, StringComparison.Ordinal))
                        {
                            newFuncName = string.Format(CultureInfo.InvariantCulture, AddToFuncFormat, renameData.NewEntitySetName);
                            codeElementsToRename.Add(codeElement, new Tuple <string, string>(newFuncName, oldFuncName));
                        }
                    }
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementProperty)
                {
                    if (targetType == RefactorTargetType.Property)
                    {
                        if (codeElement.Name.Equals(oldName, StringComparison.Ordinal))
                        {
                            // Ensure the class name matches as well
                            var splitFullName = codeElement.FullName.Split('.');

                            if (splitFullName.Length >= 2 &&
                                splitFullName[splitFullName.Length - 2].Equals(renameData.ParentEntityTypeName, StringComparison.Ordinal))
                            {
                                codeElementsToRename.Add(codeElement, new Tuple <string, string>(newName, oldName));
                            }
                        }
                    }
                    else if (targetType == RefactorTargetType.Class)
                    {
                        // There is a property on the container which contains the entity set.
                        if (codeElement.Name.Equals(renameData.OldEntitySetName, StringComparison.Ordinal))
                        {
                            codeElementsToRename.Add(
                                codeElement, new Tuple <string, string>(renameData.NewEntitySetName, renameData.OldEntitySetName));
                        }
                    }
                }
            }
        }
        internal static void CreateChangeProposals(CodeElement2 codeElement, string newName, string oldName,
            string generatedItemPath, IList<ChangeProposal> changeProposals, ObjectSearchLanguage objectSearchLanguage)
        {
            if (codeElement != null)
            {
                var searchResults = VsObjectSearchResult.Search(codeElement.FullName, objectSearchLanguage);

                if (searchResults != null)
                {
                    // VB search results don't include the designer file, since the IVsObjectList item for the designer file in VB does not contain the
                    // column number for designer file references (since VB returns a hierarchical IVsObjectList and does not show column numbers in the
                    // root nodes). So instead we'll put the info from the CodeElement into the search results, which is less
                    // than ideal since the display text is not consistent with the IVsObjectList items...
                    if (objectSearchLanguage == ObjectSearchLanguage.VB
                        && codeElement.ProjectItem != null)
                    {
                        searchResults.Add(CreateVBCodeElementSearchResult(codeElement));
                    }

                    if (searchResults.Count > 0)
                    {
                        var fileToChanges = new Dictionary<string, List<RefactorChange>>();
                        var designerFileChanges = new List<RefactorChange>();

                        foreach (var searchResult in searchResults)
                        {
                            // Don't show changes in generated file in the preview dialog since those changes will always be applied after
                            // hydration completes. Instead we just show the changes from the exercising (application) code.
                            if (!string.Equals(searchResult.FileName, generatedItemPath, StringComparison.OrdinalIgnoreCase))
                            {
                                List<RefactorChange> refactorChanges;
                                if (!fileToChanges.TryGetValue(searchResult.FileName, out refactorChanges))
                                {
                                    refactorChanges = new List<RefactorChange>();
                                    fileToChanges.Add(searchResult.FileName, refactorChanges);
                                }

                                refactorChanges.Add(
                                    new RefactorChange(
                                        searchResult.DisplayText, searchResult.DisplayText, searchResult.LineNumber,
                                        searchResult.ColumnNumber));
                            }
                            else
                            {
                                // We need to know the location of the type definition in the generated code file so we can populate the
                                // root node of the preview window, so we save off a list of all references to the renamed object in
                                // the designer file here.
                                designerFileChanges.Add(
                                    new RefactorChange(
                                        searchResult.DisplayText, searchResult.DisplayText, searchResult.LineNumber,
                                        searchResult.ColumnNumber));
                            }
                        }

                        // Add designer file change
                        var rootFileName = codeElement.ProjectItem.get_FileNames(1);
                        bool doesProjectHaveFileName;
                        var rootProjectName = VsUtils.GetProjectPathWithName(
                            codeElement.ProjectItem.ContainingProject, out doesProjectHaveFileName);

                        // The code element start line will include attributes for the class, so the get the line where the actual class name is
                        // we need to use the results from the IVsObjectSearch and get the search result immediately after the CodeElements startline.
                        var minDelta = int.MaxValue;
                        RefactorChange? rootNodeChange = null;
                        foreach (var change in designerFileChanges)
                        {
                            var lineDelta = change.LineNumber - codeElement.StartPoint.Line;

                            if (lineDelta >= 0
                                && lineDelta < minDelta)
                            {
                                minDelta = lineDelta;
                                rootNodeChange = change;
                            }
                        }

                        if (rootNodeChange != null)
                        {
                            var textChangeProposal = new VsLangTextChangeProposal(
                                rootProjectName, rootFileName, newName, codeElement.FullName, true);
                            textChangeProposal.StartColumn = rootNodeChange.Value.ColumnNumber - 1;
                            textChangeProposal.EndColumn = textChangeProposal.StartColumn + oldName.Length;
                            textChangeProposal.Length = oldName.Length;
                            textChangeProposal.StartLine = rootNodeChange.Value.LineNumber - 1;
                            textChangeProposal.EndLine = textChangeProposal.StartLine;
                            textChangeProposal.Included = true;
                            changeProposals.Add(textChangeProposal);
                        }

                        // Add application code changes
                        foreach (var fileName in fileToChanges.Keys)
                        {
                            var owningProject = VSHelpers.GetProjectForDocument(fileName);
                            var changes = fileToChanges[fileName];

                            if (changes.Count > 0
                                && owningProject != null)
                            {
                                foreach (var change in changes)
                                {
                                    // Text buffer is zero based but find all refs is one based, so subtract 1.
                                    var textBufferLine = change.LineNumber - 1;
                                    var textBufferColumn = change.ColumnNumber - 1;

                                    bool projectHasFilename;
                                    var projectFullPath = VsUtils.GetProjectPathWithName(owningProject, out projectHasFilename);
                                    var textChangeProposal = new VsLangTextChangeProposal(
                                        projectFullPath, fileName, newName, codeElement.FullName);
                                    textChangeProposal.StartColumn = textBufferColumn;
                                    textChangeProposal.EndColumn = textChangeProposal.StartColumn + oldName.Length;
                                    textChangeProposal.Length = oldName.Length;
                                    textChangeProposal.StartLine = textBufferLine;
                                    textChangeProposal.EndLine = textBufferLine;
                                    textChangeProposal.Included = true;
                                    changeProposals.Add(textChangeProposal);
                                }
                            }
                        }
                    }
                }
            }
        }
        internal static void FindRootCodeElementsToRename(
            IEnumerable<CodeElement2> codeElements,
            CodeElementRenameData renameData,
            string generatedItemPath,
            ObjectSearchLanguage objectSearchLanguage,
            ref Dictionary<CodeElement2, Tuple<string, string>> codeElementsToRename)
        {
            if (codeElementsToRename == null)
            {
                codeElementsToRename = new Dictionary<CodeElement2, Tuple<string, string>>();
            }

            var newName = renameData.NewName;
            var oldName = renameData.OldName;
            var targetType = renameData.RefactorTargetType;

            // Rename the symbols that match the old name
            foreach (var codeElement in codeElements)
            {
                if (codeElement.Kind == vsCMElement.vsCMElementNamespace)
                {
                    FindRootCodeElementsToRename(
                        codeElement.Children.OfType<CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                        ref codeElementsToRename);
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementClass)
                {
                    if (targetType == RefactorTargetType.Class)
                    {
                        if (codeElement.Name.Equals(oldName, StringComparison.Ordinal))
                        {
                            codeElementsToRename.Add(codeElement, new Tuple<string, string>(newName, oldName));
                        }

                        // If we're refactoring a class, we need to iterate another level deeper even if the name of this Type doesn't match what we're refactoring
                        // since we need to rename the AddTo*() functions
                        FindRootCodeElementsToRename(
                            codeElement.Children.OfType<CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                            ref codeElementsToRename);
                    }
                    else if (targetType == RefactorTargetType.Property)
                    {
                        // If we're refactoring a property we need to iterate another level deeper to find the property elements.
                        FindRootCodeElementsToRename(
                            codeElement.Children.OfType<CodeElement2>(), renameData, generatedItemPath, objectSearchLanguage,
                            ref codeElementsToRename);
                    }
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementFunction
                         && targetType == RefactorTargetType.Class)
                {
                    // Functions use the entity set name, so check for pluralization
                    string oldFuncName;
                    string newFuncName;

                    var function = (CodeFunction)codeElement;
                    var parentType = function.Parent as CodeType;
                    var oldFactoryFuncName = string.Format(CultureInfo.InvariantCulture, CreateFuncFormat, oldName);
                    if (parentType != null
                        && parentType.Name.Equals(oldName, StringComparison.Ordinal)
                        && function.Name.Equals(oldFactoryFuncName, StringComparison.Ordinal))
                    {
                        // We need to rename Create* factory funcs as they use the class name.
                        codeElementsToRename.Add(
                            codeElement,
                            new Tuple<string, string>(
                                string.Format(CultureInfo.InvariantCulture, CreateFuncFormat, newName), oldFactoryFuncName));
                    }
                    else
                    {
                        // We also need to rename the AddTo* funcs when we rename classes, since the class name is used in the generated func name.
                        oldFuncName = string.Format(CultureInfo.InvariantCulture, AddToFuncFormat, renameData.OldEntitySetName);

                        if (codeElement.Name.Equals(oldFuncName, StringComparison.Ordinal))
                        {
                            newFuncName = string.Format(CultureInfo.InvariantCulture, AddToFuncFormat, renameData.NewEntitySetName);
                            codeElementsToRename.Add(codeElement, new Tuple<string, string>(newFuncName, oldFuncName));
                        }
                    }
                }
                else if (codeElement.Kind == vsCMElement.vsCMElementProperty)
                {
                    if (targetType == RefactorTargetType.Property)
                    {
                        if (codeElement.Name.Equals(oldName, StringComparison.Ordinal))
                        {
                            // Ensure the class name matches as well
                            var splitFullName = codeElement.FullName.Split('.');

                            if (splitFullName.Length >= 2
                                && splitFullName[splitFullName.Length - 2].Equals(renameData.ParentEntityTypeName, StringComparison.Ordinal))
                            {
                                codeElementsToRename.Add(codeElement, new Tuple<string, string>(newName, oldName));
                            }
                        }
                    }
                    else if (targetType == RefactorTargetType.Class)
                    {
                        // There is a property on the container which contains the entity set.
                        if (codeElement.Name.Equals(renameData.OldEntitySetName, StringComparison.Ordinal))
                        {
                            codeElementsToRename.Add(
                                codeElement, new Tuple<string, string>(renameData.NewEntitySetName, renameData.OldEntitySetName));
                        }
                    }
                }
            }
        }