/// <summary> /// Explores given file, using parent batch command's methods as callbacks /// </summary> /// <param name="parentCommand"></param> /// <param name="projectItem"></param> /// <param name="maxLine">Line where parser should stop</param> /// <param name="maxIndex">Column where parser should stop</param> public void Explore(AbstractBatchCommand parentCommand, ProjectItem projectItem, int maxLine, int maxIndex) { if (parentCommand == null) { throw new ArgumentNullException("parentCommand"); } if (projectItem == null) { throw new ArgumentNullException("projectItem"); } lock (syncObject) { fullPath = projectItem.GetFullPath(); if (string.IsNullOrEmpty(fullPath)) { throw new Exception("Cannot process item " + projectItem.Name); } this.parentCommand = parentCommand; this.declaredNamespaces.Clear(); this.ClassFileName = Path.GetFileNameWithoutExtension(fullPath); this.projectItem = projectItem; this.openedElements.Clear(); // initialize type resolver if (parentCommand is BatchMoveCommand) { webConfig = WebConfig.Get(projectItem, VisualLocalizerPackage.Instance.DTE.Solution); } else { webConfig = null; } fileText = null; if (RDTManager.IsFileOpen(fullPath)) // file is open { var textLines = VLDocumentViewsManager.GetTextLinesForFile(fullPath, false); // get text buffer if (textLines == null) { return; } int lastLine, lastLineIndex; int hr = textLines.GetLastLineIndex(out lastLine, out lastLineIndex); Marshal.ThrowExceptionForHR(hr); hr = textLines.GetLineText(0, 0, lastLine, lastLineIndex, out fileText); // get plain text Marshal.ThrowExceptionForHR(hr); } else // file is closed - read it from disk { fileText = File.ReadAllText(fullPath); } Parser parser = new Parser(fileText, this, maxLine, maxIndex); // run ASP .NET parser parser.Process(); } }
public void ProcessSelectionTest() { Agent.EnsureSolutionOpen(); IVsTextView view = VLDocumentViewsManager.GetTextViewForFile(Agent.VBStringsTestFile1, true, true); IVsTextLines lines = VLDocumentViewsManager.GetTextLinesForFile(Agent.VBStringsTestFile1, false); GenericSelectionTest(Agent.BatchMoveCommand_Accessor, Agent.VBStringsTestFile1, view, lines, GetExpectedResultsFor); }
public void ProcessSelectionTest2() { Agent.EnsureSolutionOpen(); IVsTextView view = VLDocumentViewsManager.GetTextViewForFile(Agent.AspNetReferencesTestFile2, true, true); IVsTextLines lines = VLDocumentViewsManager.GetTextLinesForFile(Agent.AspNetReferencesTestFile2, false); GenericSelectionTest(Agent.BatchInlineCommand_Accessor, Agent.AspNetReferencesTestFile2, view, lines, GetExpectedResultsFor); }
/// <summary> /// For given BlockSpan located in specified file, its absolute position parameters are calculated /// </summary> protected static void CalculateAbsolutePosition(string path, BlockSpan span) { IVsTextLines view = VLDocumentViewsManager.GetTextLinesForFile(path, true); object o; view.CreateTextPoint(span.StartLine, span.StartIndex, out o); TextPoint tp = (TextPoint)o; span.AbsoluteCharOffset = tp.AbsoluteCharOffset + span.StartLine - 1; view.CreateTextPoint(span.EndLine, span.EndIndex, out o); TextPoint tp2 = (TextPoint)o; span.AbsoluteCharLength = tp2.AbsoluteCharOffset + span.EndLine - 1 - span.AbsoluteCharOffset; }
/// <summary> /// For given result item with specified ReplaceSpan calculates AbsoluteCharOffset and AbsoluteCharLength /// </summary> protected static void CalculateAbsolutePosition(AbstractResultItem item) { IVsTextLines view = VLDocumentViewsManager.GetTextLinesForFile(item.SourceItem.GetFullPath(), true); object o; view.CreateTextPoint(item.ReplaceSpan.iStartLine, item.ReplaceSpan.iStartIndex, out o); TextPoint tp = (TextPoint)o; item.AbsoluteCharOffset = tp.AbsoluteCharOffset + item.ReplaceSpan.iStartLine - 1; view.CreateTextPoint(item.ReplaceSpan.iEndLine, item.ReplaceSpan.iEndIndex, out o); TextPoint tp2 = (TextPoint)o; item.AbsoluteCharLength = tp2.AbsoluteCharOffset + item.ReplaceSpan.iEndLine - 1 - item.AbsoluteCharOffset; }
public void VBInlineTest() { Agent.EnsureSolutionOpen(); VBInlineCommand_Accessor target = new VBInlineCommand_Accessor(); Window window = Agent.GetDTE().OpenFile(null, Agent.VBReferencesTestFile1); IVsTextView view = VLDocumentViewsManager.GetTextViewForFile(Agent.VBReferencesTestFile1, true, true); IVsTextLines lines = VLDocumentViewsManager.GetTextLinesForFile(Agent.VBReferencesTestFile1, false); var expected = VBBatchInlineTest.GetExpectedResultsFor(Agent.VBReferencesTestFile1); RunTest(target, view, lines, expected); window.Detach(); window.Close(vsSaveChanges.vsSaveChangesNo); }
public void CSharpMoveTest() { Agent.EnsureSolutionOpen(); CSharpMoveToResourcesCommand_Accessor target = new CSharpMoveToResourcesCommand_Accessor(); Window window = Agent.GetDTE().OpenFile(null, Agent.CSharpStringsTestFile1); IVsTextView view = VLDocumentViewsManager.GetTextViewForFile(Agent.CSharpStringsTestFile1, true, true); IVsTextLines lines = VLDocumentViewsManager.GetTextLinesForFile(Agent.CSharpStringsTestFile1, false); var expected = CSharpBatchMoveTest.GetExpectedResultsFor(Agent.CSharpStringsTestFile1); RunTest(target, view, lines, expected); window.Detach(); window.Close(vsSaveChanges.vsSaveChangesNo); }
/// <summary> /// Generic test method /// </summary> /// <param name="openFiles">True if the files should be opened first</param> /// <param name="fullName">True if the "Use full names" policy should be applied</param> /// <param name="mark">True if the "Mark with VL_NO_LOC policy should be applied"</param> /// <param name="testFiles">Files to test</param> /// <param name="targetFiles">ResX files where resources can be moved</param> private void InternalFileMoveTest(bool openFiles, bool fullName, bool mark, string[] testFiles, string[] targetFiles) { // backup the files Dictionary <string, string> backups = CreateBackupsOf(testFiles); // run the "batch move" command to get result items List <CodeStringResultItem> items = BatchMoveLookup(testFiles); // open the necessary files SetFilesOpened(testFiles, openFiles); // initialize ResX destination files Dictionary <string, ResXProjectItem> resxItems = InitResxItems(targetFiles, Agent.GetDTE().Solution.FindProjectItem(testFiles[0]).ContainingProject); // initialize the "batch move" tool window and grid Dictionary <ResXProjectItem, int> resxCounts; Dictionary <ProjectItem, int> sourceItemCounts; int expectedToBeMarked; BatchMoveToResourcesToolWindow_Accessor window = InitBatchToolWindow(resxItems.Values.ToList(), items, fullName, mark, out resxCounts, out sourceItemCounts, out expectedToBeMarked); try { // execute window.RunClick(null, null); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchMoveCommand), false); // verify every ResX file contains the correct number of resources foreach (ResXProjectItem target in resxItems.Values) { Assert.AreEqual(resxCounts.ContainsKey(target) ? resxCounts[target] : 0, GetResourcesCountIn(target)); } // run the "inline" command to verify all references are valid int checkedCount = resxCounts.Sum((pair) => { return(pair.Value); }); List <CodeReferenceResultItem> inlineResults = BatchInlineLookup(testFiles); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchInlineCommand), false); Assert.AreEqual(checkedCount, inlineResults.Count); // test if every unchecked string result item was marked if (mark) { int markedAfter = BatchMoveLookup(testFiles).Count((item) => { return(item.IsMarkedWithUnlocalizableComment); }); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchMoveCommand), false); Assert.AreEqual(expectedToBeMarked, markedAfter, "mark"); } // test if qualified name was really used if (fullName) { foreach (var result in inlineResults) { AspNetCodeReferenceResultItem citem = result as AspNetCodeReferenceResultItem; if (citem == null || !citem.ComesFromWebSiteResourceReference) { Assert.AreEqual(result.OriginalReferenceText, result.FullReferenceText); } } } // check if no import statement has been added twice foreach (string path in testFiles) { CheckForDuplicateUsings(path); } if (openFiles) { // use undo manager to revert the changes foreach (string file in testFiles) { var win = VsShellUtilities.GetWindowObject(VLDocumentViewsManager.GetWindowFrameForFile(file, false)); ProjectItem pitem = Agent.GetDTE().Solution.FindProjectItem(file); int count = sourceItemCounts.ContainsKey(pitem) ? sourceItemCounts[pitem] : 0; IOleUndoManager manager; VLDocumentViewsManager.GetTextLinesForFile(file, false).GetUndoManager(out manager); List <IOleUndoUnit> list = manager.RemoveTopFromUndoStack(count); foreach (AbstractUndoUnit unit in list) { unit.Undo(); } Assert.AreEqual(File.ReadAllText(backups[file]), File.ReadAllText(file)); } // check that all changes were fully reverted int sum = resxItems.Values.Sum((item) => { return(GetResourcesCountIn(item)); }); Assert.AreEqual(0, sum); } } finally { // close the files SetFilesOpened(testFiles, false); // restore the backups RestoreBackups(backups); // clear ResX files foreach (ResXProjectItem target in resxItems.Values) { ClearFile(target); } VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchMoveCommand), false); } }
/// <summary> /// Generic testing method /// </summary> /// <param name="fileOpened">True if files should be opened</param> /// <param name="referenceFiles">Files to test</param> /// <param name="correction">Number of string literals reported by the "batch move" command in the files</param> private void InternalFileTest(bool fileOpened, string[] referenceFiles, int correction) { // backup the files Dictionary <string, string> backups = CreateBackupsOf(referenceFiles); // open/close the files SetFilesOpened(referenceFiles, fileOpened); // run inline command in order to obtain result items List <CodeReferenceResultItem> inlineList = BatchInlineLookup(referenceFiles); // init the tool window and the grid int checkedCount; Dictionary <ProjectItem, int> sourceItemsCounts; BatchInlineToolWindow_Accessor window = InitBatchWindow(inlineList, out sourceItemsCounts, out checkedCount); try { // run the command window.RunClick(null, null); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchInlineCommand), false); // run "batch move" command List <CodeStringResultItem> moveList = BatchMoveLookup(referenceFiles); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchMoveCommand), false); // the number of string literals found by the "batch move" command, minus the string literals that were // already there should be equal to the number of inlined result items Assert.AreEqual(checkedCount, moveList.Count - correction); // check correct value was inlined int i = 0, j = 0; for (; i < checkedCount;) { while (!inlineList[i].MoveThisItem) { i++; } while (moveList[j].Value != inlineList[i].Value) { j++; } Assert.AreEqual(inlineList[i].Value, moveList[j].Value); i++; j++; } // use the undo manager to revert the changes if (fileOpened) { foreach (string file in referenceFiles) { IOleUndoManager undoManager; VLDocumentViewsManager.GetTextLinesForFile(file, false).GetUndoManager(out undoManager); foreach (AbstractUndoUnit unit in undoManager.RemoveTopFromUndoStack(sourceItemsCounts[Agent.GetDTE().Solution.FindProjectItem(file)])) { unit.Undo(); } Assert.AreEqual(File.ReadAllText(backups[file]), File.ReadAllText(file)); } } } finally { // close the files SetFilesOpened(referenceFiles, false); VLDocumentViewsManager.CloseInvisibleWindows(typeof(BatchInlineCommand), false); // restore backups RestoreBackups(backups); } }
/// <summary> /// Add string data from given ResX file to the list of data for translation /// </summary> private void AddDataForTranslation(GlobalTranslateProjectItem item, List <AbstractTranslateInfoItem> data) { string path = item.ProjectItem.GetFullPath(); if (RDTManager.IsFileOpen(path)) // file is open { object docData = VLDocumentViewsManager.GetDocData(path); // get document buffer if (docData is ResXEditor) // document is opened in ResX editor -> use custom method to get string data { ResXEditor editor = (ResXEditor)docData; editor.UIControl.AddForTranslation(data); } else // document is opened in original VS editor { IVsTextLines lines = VLDocumentViewsManager.GetTextLinesForFile(path, false); string text = VLDocumentViewsManager.GetTextFrom(lines); // get plain text of ResX file ResXResourceReader reader = null; BufferTranslateInfoItem prev = null; BufferTranslateInfoItem first = null; try { reader = ResXResourceReader.FromFileContents(text); reader.UseResXDataNodes = true; // add all string resources to the list // items are linked like a linked-list, allowing ApplyTranslation to work foreach (DictionaryEntry entry in reader) { ResXDataNode node = (entry.Value as ResXDataNode); if (node.HasValue <string>()) { BufferTranslateInfoItem translateItem = new BufferTranslateInfoItem(); translateItem.ResourceKey = entry.Key.ToString(); translateItem.Value = node.GetValue <string>(); translateItem.Filename = path; translateItem.Applied = false; translateItem.GlobalTranslateItem = item; translateItem.Prev = prev; translateItem.IVsTextLines = lines; data.Add(translateItem); prev = translateItem; if (first == null) { first = translateItem; } } else { item.NonStringData.Add(node); } } if (first != null) { first.Prev = prev; } } finally { if (reader != null) { reader.Close(); } } } } else // file is closed { ResXProjectItem resxItem = ResXProjectItem.ConvertToResXItem(item.ProjectItem, item.ProjectItem.ContainingProject); resxItem.Load(); loadedResxItems.Add(resxItem); // add string data from ResX file resxItem.AddAllStringReferencesUnique(data); } }