private static VsObjectSearchResult CreateVBCodeElementSearchResult(CodeElement2 codeElement) { var column = codeElement.StartPoint.LineCharOffset; var line = codeElement.StartPoint.Line; int lineLength; string lineText; string prefix; // Try to locate the element name on the startline. using (var textBuffer = VsTextLinesFromFile.Load(codeElement.ProjectItem.get_FileNames(1))) { // Buffer values are zero based, codeElement values are 1 based. var bufferLine = line - 1; NativeMethods.ThrowOnFailure(textBuffer.GetLengthOfLine(bufferLine, out lineLength)); NativeMethods.ThrowOnFailure(textBuffer.GetLineText(bufferLine, 0, bufferLine, lineLength, out lineText)); } // Skip past the prefix, which is different depending on whether we are processing a class/property/function switch (codeElement.Kind) { case vsCMElement.vsCMElementClass: prefix = VBClassKeyword; break; case vsCMElement.vsCMElementProperty: prefix = VBPropertyKeyword; break; case vsCMElement.vsCMElementFunction: prefix = VBFunctionKeyword; break; default: throw new NotImplementedException( "CreateVBCodeElementSearchResult() does not implement handlers for CodeElement type: " + codeElement.Kind.ToString()); } var prefixStartIndex = lineText.IndexOf(prefix, 0, StringComparison.OrdinalIgnoreCase); if (prefixStartIndex >= 0) { var prefixEndIndex = prefixStartIndex + prefix.Length; if (prefixEndIndex < lineText.Length) { var elementNameStartIndex = lineText.IndexOf(codeElement.Name, prefixEndIndex, StringComparison.OrdinalIgnoreCase); if (elementNameStartIndex >= 0) { // Buffer values are zero based, FindAllRef values are 1 based. column = elementNameStartIndex + 1; } } } return(new VsObjectSearchResult(codeElement.ProjectItem.get_FileNames(1), codeElement.FullName, line, column)); }
protected static List <PreviewChangesNode> CreatePreviewNodesForVsLang( IList <FileChange> fileChanges, bool placeNodesUnderSingleRoot = false) { var vsLangObjectNodes = new List <PreviewChangesNode>(); var rootToFileToChangesMap = new Dictionary <string, Dictionary <string, List <PreviewChangesNode> > >(); var isCSharpChange = true; foreach (var fileChange in fileChanges) { if (fileChange.ChangeList != null) { if (fileChange.ChangeList.Count > 0) { using (var textBuffer = VsTextLinesFromFile.Load(fileChange.FileName)) { if (textBuffer != null) { foreach ( var vsLangTextChange in fileChange.ChangeList.SelectMany(cl => cl.Value).OfType <VsLangTextChangeProposal>()) { if (vsLangTextChange.IsRootChange) { // Create object definition node var rootNode = new PreviewChangesNode( vsLangTextChange.ObjectDefinitionFullName , new VSTREEDISPLAYDATA() , vsLangTextChange.ObjectDefinitionFullName , new List <PreviewChangesNode>() , vsLangTextChange); rootNode.CheckState = vsLangTextChange.Included ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked; vsLangObjectNodes.Add(rootNode); // It's possible that a non-root change was processed first, in which case the dictionary will already be updated // with the root node name. This means we need to check the dictionary before adding to it. if (!rootToFileToChangesMap.ContainsKey(vsLangTextChange.ObjectDefinitionFullName)) { rootToFileToChangesMap.Add( vsLangTextChange.ObjectDefinitionFullName, new Dictionary <string, List <PreviewChangesNode> >()); } } else { // Get display text, trim the leading space of the text for display purpose. var displayText = string.Empty; int lineLength; if (ErrorHandler.Succeeded(textBuffer.GetLengthOfLine(vsLangTextChange.StartLine, out lineLength))) { if ( ErrorHandler.Succeeded( textBuffer.GetLineText( vsLangTextChange.StartLine, 0, vsLangTextChange.StartLine, lineLength, out displayText))) { var length = displayText.Length; displayText = displayText.TrimStart(); var spaceLength = length - displayText.Length; Debug.Assert( spaceLength <= vsLangTextChange.StartColumn, "Start column of selection is negative, HydratedVsLangRefactor.CreatePreviewNodeForChanges()"); if (spaceLength <= vsLangTextChange.StartColumn) { var changeNodeDisplayData = new VSTREEDISPLAYDATA(); changeNodeDisplayData.State = (uint)_VSTREEDISPLAYSTATE.TDS_FORCESELECT; changeNodeDisplayData.ForceSelectStart = (ushort)(vsLangTextChange.StartColumn - spaceLength); changeNodeDisplayData.ForceSelectLength = (ushort)(vsLangTextChange.Length); var changeNode = new PreviewChangesNode( displayText, changeNodeDisplayData, displayText, null, vsLangTextChange); // Add checked checkbox changeNode.ShowCheckBox = true; changeNode.CheckState = vsLangTextChange.Included ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked; // Apply the language service to this change. Guid languageServiceId; textBuffer.GetLanguageServiceID(out languageServiceId); changeNode.LanguageServiceID = languageServiceId; Dictionary <string, List <PreviewChangesNode> > fileToChangesMap; if (rootToFileToChangesMap.TryGetValue( vsLangTextChange.ObjectDefinitionFullName, out fileToChangesMap)) { List <PreviewChangesNode> changeNodes; if (fileToChangesMap.TryGetValue(fileChange.FileName, out changeNodes)) { changeNodes.Add(changeNode); } else { // There are no changes for the file listed under this root node, so we need to create it changeNodes = new List <PreviewChangesNode> { changeNode }; fileToChangesMap.Add(fileChange.FileName, changeNodes); } } else { // There are no changes processed yet for this object name, so we need to update our dictionary with // markers for creating a new root node, a new file node, and a new change node. fileToChangesMap = new Dictionary <string, List <PreviewChangesNode> >(); fileToChangesMap.Add( fileChange.FileName, new List <PreviewChangesNode> { changeNode }); rootToFileToChangesMap.Add( vsLangTextChange.ObjectDefinitionFullName, fileToChangesMap); } } } } } } } } } } } // Now that all the changes have been sorted under the correct root nodes in our dictionary, create the File nodes that connect // the root nodes to the change nodes. foreach (var rootNode in vsLangObjectNodes) { Dictionary <string, List <PreviewChangesNode> > fileToChangesMap; if (rootToFileToChangesMap.TryGetValue(rootNode.DisplayText, out fileToChangesMap)) { if (fileToChangesMap != null) { foreach (var fileName in fileToChangesMap.Keys) { var fileNodeDisplayData = new VSTREEDISPLAYDATA(); if (FileExtensions.VbExt.Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase)) { fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT; isCSharpChange = false; } else { fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE; } var shortFileName = Path.GetFileName(fileName); var checkState = DetermineCheckState(fileToChangesMap[fileName]); var fileNode = new PreviewChangesNode(shortFileName, fileNodeDisplayData, shortFileName, null, null); fileNode.AddChildNodes(fileToChangesMap[fileName]); // Add checked checkbox fileNode.ShowCheckBox = true; fileNode.CheckState = checkState; rootNode.AddChildNode(fileNode); // Update root check state if (rootNode.ChildList.Count == 1) { // This is the first child, so the root should match the child check state rootNode.CheckState = checkState; } else { switch (rootNode.CheckState) { case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked: { if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked || checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked) { rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked; } break; } case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked: { if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked || checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked) { rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked; } break; } } } } } } } if (placeNodesUnderSingleRoot) { PreviewChangesNode rootNode; var fileNodeDisplayData = new VSTREEDISPLAYDATA(); if (isCSharpChange) { fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE; rootNode = new PreviewChangesNode(CSharpRootNodeText, fileNodeDisplayData, null, null, null); } else { fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT; rootNode = new PreviewChangesNode(VBRootNodeText, fileNodeDisplayData, null, null, null); } rootNode.ShowCheckBox = true; rootNode.CheckState = DetermineCheckState(vsLangObjectNodes); rootNode.AddChildNodes(vsLangObjectNodes); return(new List <PreviewChangesNode> { rootNode }); } else { return(vsLangObjectNodes); } }