예제 #1
0
 /// <summary>
 /// Set opened-state of the specified files
 /// </summary>
 /// <param name="testFiles"></param>
 /// <param name="shouldBeOpened">True if files should be opened, false otherwise</param>
 protected void SetFilesOpened(string[] testFiles, bool shouldBeOpened)
 {
     foreach (string sourcePath in testFiles)
     {
         if (!shouldBeOpened && RDTManager.IsFileOpen(sourcePath))
         {
             var win = VsShellUtilities.GetWindowObject(VLDocumentViewsManager.GetWindowFrameForFile(sourcePath, false));
             // close the window
             win.Detach();
             win.Close(vsSaveChanges.vsSaveChangesNo);
         }
         if (shouldBeOpened)
         {
             Window win = null;
             // open the file and activate the window
             if (!RDTManager.IsFileOpen(sourcePath))
             {
                 win = Agent.GetDTE().OpenFile(null, sourcePath);
             }
             else
             {
                 win = VsShellUtilities.GetWindowObject(VLDocumentViewsManager.GetWindowFrameForFile(sourcePath, true));
             }
             Assert.IsNotNull(win, "Window cannot be opened " + sourcePath);
             win.Visible = true;
             win.Activate();
         }
     }
 }
예제 #2
0
        /// <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();
            }
        }
        /// <summary>
        /// Modifes lock on the document. This lock persists if document is closed and reopened.
        /// </summary>
        /// <param name="path">File path</param>
        /// <param name="setreadonly">True to set document readonly</param>
        public static void SetFileReadonly(string path, bool setreadonly)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (RDTManager.IsFileOpen(path))   // file is open
            {
                IVsWindowFrame frame = DocumentViewsManager.GetWindowFrameForFile(path, false);
                object         docData;
                int            hr = frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out docData); // get document buffer
                Marshal.ThrowExceptionForHR(hr);

                if (docData is ResXEditor)                          // file is opened in ResXEditor
                {
                    (docData as ResXEditor).ReadOnly = setreadonly; // use custom method to set it readonly
                }
                else                                                // file is opened in VS editor
                {
                    Document document = DTE.Documents.Item(path);
                    document.ReadOnly = setreadonly;
                }
                // add/remove the document from locked documents list
                if (setreadonly)
                {
                    if (!lockedDocuments.Contains(path))
                    {
                        lockedDocuments.Add(path);
                    }
                }
                else
                {
                    lockedDocuments.Remove(path);
                }
            }
            else                 // file is closed
            {
                if (setreadonly) // add file to waiting documents set
                {
                    if (!lockedDocumentsWaiting.Contains(path))
                    {
                        lockedDocumentsWaiting.Add(path);
                    }
                }
                else     // remove the file from waiting documents
                {
                    lockedDocumentsWaiting.Remove(path);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Treats given ProjectItem as a VB code file, using VBCodeExplorer to examine the file. LookInVB method is called as a callback,
        /// given plain methods text.
        /// </summary>
        protected override void ProcessVB(ProjectItem projectItem, Predicate <CodeElement> exploreable, bool verbose)
        {
            if (isInitial || editorInstance.UIControl.sourceFilesThatNeedUpdate.Contains(projectItem.GetFullPath().ToLower()))
            {
                base.ProcessVB(projectItem, exploreable, verbose);
            }
            else
            {
                bool           fileOpened;
                FileCodeModel2 codeModel = projectItem.GetCodeModel(false, false, out fileOpened);

                if (codeModel == null && !RDTManager.IsFileOpen(projectItem.GetFullPath()))
                {
                    editorInstance.UIControl.RegisterAsStaticReferenceSource(projectItem);
                    return;
                }

                if (codeModel == null)
                {
                    if (verbose)
                    {
                        VLOutputWindow.VisualLocalizerPane.WriteLine("\tCannot process {0}, file code model does not exist.", projectItem.Name);
                    }
                    return;
                }
                if (verbose)
                {
                    VLOutputWindow.VisualLocalizerPane.WriteLine("\tProcessing {0}", projectItem.Name);
                }

                currentlyProcessedItem = projectItem;

                try {
                    VBCodeExplorer.Instance.Explore(this, exploreable, codeModel);
                } catch (COMException ex) {
                    if (ex.ErrorCode == -2147483638)
                    {
                        VLOutputWindow.VisualLocalizerPane.WriteLine("\tError occured during processing {0} - the file is not yet compiled.", projectItem.Name);
                    }
                    else
                    {
                        throw;
                    }
                }

                currentlyProcessedItem = null;
            }
            editorInstance.UIControl.sourceFilesThatNeedUpdate.Remove(projectItem.GetFullPath().ToLower());
        }
예제 #5
0
 /// <summary>
 /// Restores files from backups - copy the backuped file back, overwriting the current. The backuped file is deleted.
 /// </summary>
 protected void RestoreBackups(Dictionary <string, string> backups)
 {
     foreach (var pair in backups)
     {
         if (RDTManager.IsFileOpen(pair.Key))
         {
             RDTManager.SetIgnoreFileChanges(pair.Key, true);
             File.Copy(pair.Value, pair.Key, true);
             File.Delete(pair.Value);
             RDTManager.SilentlyReloadFile(pair.Key);
             RDTManager.SetIgnoreFileChanges(pair.Key, false);
         }
         else
         {
             File.Copy(pair.Value, pair.Key, true);
             File.Delete(pair.Value);
         }
     }
 }
예제 #6
0
        /// <summary>
        /// Returns code model for given item
        /// </summary>
        public static FileCodeModel2 GetCodeModel(this ProjectItem item, bool throwOnNull, bool openFileIfNecessary, out bool fileOpened)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            fileOpened = false;

            if (item.FileCodeModel == null && !RDTManager.IsFileOpen(item.GetFullPath()) && openFileIfNecessary)
            {
                item.Open(EnvDTE.Constants.vsext_vk_Code);
                fileOpened = true;
            }

            if (item.FileCodeModel == null && throwOnNull)
            {
                throw new InvalidOperationException("FileCodeModel for " + item.Name + " cannot be obtained. Try recompiling the file.");
            }
            return((FileCodeModel2)item.FileCodeModel);
        }
예제 #7
0
        /// <summary>
        /// Flushes current Data. If the file is closed, it means write data to disk; otherwise corresponding file buffer is modified.
        /// </summary>
        public void Flush()
        {
            if (!dataChangedInBatchMode && IsInBatchMode)
            {
                return;
            }
            string path = InternalProjectItem.GetFullPath();

            if (RDTManager.IsFileOpen(path))
            {
                VLDocumentViewsManager.SaveDataToBuffer(data, path); // modify in-memory buffer of this file
            }
            else
            {
                // write data to disk
                ResXResourceWriter writer = null;
                try {
                    writer          = new ResXResourceWriter(path);
                    writer.BasePath = Path.GetDirectoryName(path);

                    foreach (var pair in data)
                    {
                        writer.AddResource(pair.Value);
                    }
                    writer.Generate();
                } finally {
                    if (writer != null)
                    {
                        writer.Close();
                    }
                }
            }

            // regenerate designer item
            if (DesignerItem != null)
            {
                RDTManager.SilentlyModifyFile(DesignerItem.GetFullPath(), (string p) => {
                    RunCustomTool();
                });
            }
        }
예제 #8
0
        /// <summary>
        /// Loads file's content into memory
        /// </summary>
        public void Load()
        {
            if (IsLoaded)
            {
                return;
            }

            string path = InternalProjectItem.GetFullPath();

            if (RDTManager.IsFileOpen(path))   // file is open - read from VS buffer
            {
                VLDocumentViewsManager.LoadDataFromBuffer(ref data, path);
            }
            else     // file is closed - read from disk
            {
                ResXResourceReader reader = null;
                try {
                    data                    = new Dictionary <string, ResXDataNode>();
                    reader                  = new ResXResourceReader(path);
                    reader.BasePath         = Path.GetDirectoryName(path);
                    reader.UseResXDataNodes = true;

                    foreach (DictionaryEntry entry in reader)
                    {
                        data.Add(entry.Key.ToString().ToLower(), entry.Value as ResXDataNode);
                    }
                } finally {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }
            }

            IsLoaded = true;
        }
예제 #9
0
        public void Move(List <CodeStringResultItem> dataList, ref int errorRows)
        {
            // sort according to position
            dataList.Sort(new ResultItemsPositionCompararer <CodeStringResultItem>());

            for (int i = dataList.Count - 1; i >= 0; i--)
            {
                try {
                    // initialization of data
                    CodeStringResultItem resultItem   = dataList[i];
                    string              path          = resultItem.SourceItem.GetFullPath();
                    ReferenceString     referenceText = null;
                    bool                addUsingBlock = false;
                    CONTAINS_KEY_RESULT keyConflict   = CONTAINS_KEY_RESULT.DOESNT_EXIST;

                    if (resultItem.MoveThisItem) // row was checked in the toolwindow
                    {
                        Validate(resultItem);    // check that key, value and destination item was specifed and that row has no errors
                        if (!resultItem.DestinationItem.IsLoaded)
                        {
                            resultItem.DestinationItem.Load();
                        }
                        if (!loadedResxItems.Contains(resultItem.DestinationItem))
                        {
                            loadedResxItems.Add(resultItem.DestinationItem);
                        }

                        // check if such item already exists in destination file
                        keyConflict = resultItem.DestinationItem.GetKeyConflictType(resultItem.Key, resultItem.Value, true);
                        if (keyConflict == CONTAINS_KEY_RESULT.EXISTS_WITH_DIFF_VALUE)
                        {
                            throw new InvalidOperationException(string.Format("Key \"{0}\" already exists with different value.", resultItem.Key));
                        }
                        resultItem.Key = resultItem.DestinationItem.GetRealKey(resultItem.Key); // if key already exists, return its name (solves case-sensitivity problems)

                        NamespacesList usedNamespaces = GetUsedNamespacesFor(resultItem);

                        if (UseFullName || resultItem.MustUseFullName || (resultItem.Language == LANGUAGE.VB && resultItem.DestinationItem.IsProjectDefault(resultItem.SourceItem.ContainingProject)))   // reference will contain namespace
                        {
                            referenceText = new ReferenceString(resultItem.DestinationItem.Namespace, resultItem.DestinationItem.Class, resultItem.Key);
                            addUsingBlock = false; // no using block will be added
                        }
                        else
                        {
                            // use resolver whether it is ok to add using block
                            addUsingBlock = usedNamespaces.ResolveNewElement(resultItem.DestinationItem.Namespace, resultItem.DestinationItem.Class, resultItem.Key,
                                                                             resultItem.SourceItem.ContainingProject, out referenceText);
                        }
                        if (addUsingBlock)   // new using block will be added
                        {
                            if (!usedNamespacesCache.ContainsKey(resultItem.SourceItem))
                            {
                                usedNamespacesCache.Add(resultItem.SourceItem, new NamespacesList());
                            }
                            foreach (var pair in usedNamespacesCache)
                            {
                                if (!pair.Value.ContainsNamespace(resultItem.DestinationItem.Namespace))
                                {
                                    pair.Value.Add(resultItem.DestinationItem.Namespace, null, true);
                                }
                            }
                        }
                    }

                    if (RDTManager.IsFileOpen(path) && RDTManager.IsFileVisible(path))                                                    // file is open
                    {
                        if (resultItem.MoveThisItem || (MarkUncheckedStringsWithComment && !resultItem.IsMarkedWithUnlocalizableComment)) // string literal in text will be modified (referenced or marked with comment)
                        {
                            if (!buffersCache.ContainsKey(path))
                            {
                                // load file's buffer
                                IVsTextLines textLines = DocumentViewsManager.GetTextLinesForFile(path, false);
                                buffersCache.Add(path, textLines);

                                IOleUndoManager m;
                                // get file's undo manager
                                int hr = textLines.GetUndoManager(out m);
                                Marshal.ThrowExceptionForHR(hr);
                                undoManagersCache.Add(path, m);
                            }
                        }

                        if (resultItem.MoveThisItem)
                        {
                            // perform the text replacement
                            MoveToResource(buffersCache[path], resultItem, referenceText);

                            if (resultItem.IsConst && resultItem.CodeModelSource is CodeVariable2)
                            {
                                CodeVariable2 codeVar = (CodeVariable2)resultItem.CodeModelSource;
                                codeVar.ConstKind = vsCMConstKind.vsCMConstKindNone;
                            }

                            if (addUsingBlock)
                            {
                                // add using block to the source file
                                int beforeLines, afterLines;
                                buffersCache[path].GetLineCount(out beforeLines);
                                resultItem.AddUsingBlock(buffersCache[path]);
                                buffersCache[path].GetLineCount(out afterLines);
                                int diff = afterLines - beforeLines;

                                // because of the previous step, it is necessary to adjust position of all not-yet referenced result items
                                for (int j = i; j >= 0; j--)
                                {
                                    var item = dataList[j];
                                    if (item.SourceItem == resultItem.SourceItem)
                                    {
                                        TextSpan ts = new TextSpan();
                                        ts.iEndIndex     = item.ReplaceSpan.iEndIndex;
                                        ts.iEndLine      = item.ReplaceSpan.iEndLine + diff;
                                        ts.iStartIndex   = item.ReplaceSpan.iStartIndex;
                                        ts.iStartLine    = item.ReplaceSpan.iStartLine + diff;
                                        item.ReplaceSpan = ts;
                                    }
                                }
                            }

                            // previous step (replace and possibly new using block) caused undo unit to be added - remove it
                            int unitsToRemoveCount    = (resultItem.IsConst && addUsingBlock ? 3 : (resultItem.IsConst || addUsingBlock ? 2 : 1));
                            List <IOleUndoUnit> units = undoManagersCache[path].RemoveTopFromUndoStack(unitsToRemoveCount);

                            // and add custom undo unit
                            AbstractUndoUnit newUnit = null;
                            if (keyConflict == CONTAINS_KEY_RESULT.DOESNT_EXIST)
                            {
                                newUnit = new MoveToResourcesUndoUnit(resultItem.Key, resultItem.Value, resultItem.DestinationItem);
                            }
                            else if (keyConflict == CONTAINS_KEY_RESULT.EXISTS_WITH_SAME_VALUE)
                            {
                                newUnit = new MoveToResourcesReferenceUndoUnit(resultItem.Key);
                            }

                            newUnit.AppendUnits.AddRange(units);
                            undoManagersCache[path].Add(newUnit);
                        }
                        else if (MarkUncheckedStringsWithComment && !resultItem.IsMarkedWithUnlocalizableComment)     // string literal should be marked with comment
                        {
                            AspNetStringResultItem aitem = resultItem as AspNetStringResultItem;

                            // this operation is only possible if string literal comes from C# code
                            if (resultItem is CSharpStringResultItem || (aitem != null && aitem.ComesFromCodeBlock && aitem.Language == LANGUAGE.CSHARP))
                            {
                                // add the comment
                                int c = MarkAsNoLoc(buffersCache[path], resultItem);

                                // add undo unit
                                List <IOleUndoUnit> units = undoManagersCache[path].RemoveTopFromUndoStack(1);
                                MarkAsNotLocalizedStringUndoUnit newUnit = new MarkAsNotLocalizedStringUndoUnit(resultItem.Value);
                                newUnit.AppendUnits.AddRange(units);
                                undoManagersCache[path].Add(newUnit);
                            }
                        }
                    }
                    else     // file is closed
                    // same as with open file, only operating with text, not buffers

                    {
                        if (resultItem.MoveThisItem || (MarkUncheckedStringsWithComment && !resultItem.IsMarkedWithUnlocalizableComment))   // string literal will be modified
                        // load file's text into the cache
                        {
                            if (!filesCache.ContainsKey(path))
                            {
                                filesCache.Add(path, new StringBuilder(File.ReadAllText(path)));
                            }
                        }

                        if (resultItem.IsConst && resultItem.CodeModelSource is CodeVariable2)
                        {
                            CodeVariable2 codeVar = (CodeVariable2)resultItem.CodeModelSource;
                            fieldsToRemoveConst.Add(codeVar);
                        }

                        if (resultItem.MoveThisItem)
                        {
                            StringBuilder b = filesCache[path];

                            // perform the replacement
                            string insertText = resultItem.GetReferenceText(referenceText);
                            b.Remove(resultItem.AbsoluteCharOffset, resultItem.AbsoluteCharLength);
                            b.Insert(resultItem.AbsoluteCharOffset, insertText);

                            if (addUsingBlock)
                            {
                                // add using block
                                if (!newUsingsPlan.ContainsKey(path))
                                {
                                    newUsingsPlan.Add(path, new List <string>());
                                }
                                newUsingsPlan[path].Add(resultItem.DestinationItem.Namespace);
                            }
                        }
                        else if (MarkUncheckedStringsWithComment && !resultItem.IsMarkedWithUnlocalizableComment)
                        {
                            AspNetStringResultItem aitem = resultItem as AspNetStringResultItem;

                            if (resultItem is CSharpStringResultItem || (aitem != null && aitem.ComesFromCodeBlock && aitem.Language == LANGUAGE.CSHARP))
                            {
                                StringBuilder b = filesCache[path];
                                b.Insert(resultItem.AbsoluteCharOffset, resultItem.NoLocalizationComment);
                            }
                        }
                    }

                    if (resultItem.MoveThisItem && keyConflict == CONTAINS_KEY_RESULT.DOESNT_EXIST)
                    {
                        if (!resultItem.DestinationItem.IsInBatchMode)
                        {
                            resultItem.DestinationItem.BeginBatch();
                        }
                        // add the key to the ResX file
                        resultItem.DestinationItem.AddString(resultItem.Key, resultItem.Value);
                    }
                } catch (Exception ex) {
                    errorRows++;
                    VLOutputWindow.VisualLocalizerPane.WriteException(ex);
                }
            }

            // add using blocks to closed files texts
            foreach (var pair in newUsingsPlan)
            {
                foreach (string nmspc in pair.Value)
                {
                    AddUsingBlockTo(pair.Key, nmspc);
                }
            }

            // flush closed files texts
            foreach (var pair in filesCache)
            {
                if (RDTManager.IsFileOpen(pair.Key))
                {
                    RDTManager.SetIgnoreFileChanges(pair.Key, true);
                    File.WriteAllText(pair.Key, pair.Value.ToString());
                    RDTManager.SetIgnoreFileChanges(pair.Key, false);
                    RDTManager.SilentlyReloadFile(pair.Key);
                }
                else
                {
                    File.WriteAllText(pair.Key, pair.Value.ToString());
                }
            }

            // remove 'const' modifier from fields in closed files
            HashSet <ProjectItem> itemsToSave = new HashSet <ProjectItem>();

            foreach (CodeVariable2 codeVar in fieldsToRemoveConst)
            {
                codeVar.ConstKind = vsCMConstKind.vsCMConstKindNone;
                itemsToSave.Add(codeVar.ProjectItem);
            }
            foreach (ProjectItem item in itemsToSave)
            {
                item.Save(null);
            }

            foreach (ResXProjectItem item in loadedResxItems)
            {
                if (item.IsInBatchMode)
                {
                    item.EndBatch();
                }
                item.Unload();
            }
            if (errorRows > 0)
            {
                throw new Exception("Error occured while processing some rows - see Output window for details.");
            }
        }
        /// <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);
            }
        }
        public void Inline(List <CodeReferenceResultItem> dataList, bool externalChange, ref int errorRows)
        {
            // sort according to position
            dataList.Sort(new ResultItemsPositionCompararer <CodeReferenceResultItem>());

            // start with the last items - not necessary to adjust position of many items after replace
            for (int i = dataList.Count - 1; i >= 0; i--)
            {
                try {
                    CodeReferenceResultItem resultItem = dataList[i];

                    if (resultItem.MoveThisItem)   // the item was checked in the toolwindow grid
                    {
                        int absoluteStartIndex, absoluteLength;

                        // get text that replaces the result item
                        string text = GetReplaceString(resultItem);

                        // get position information about block to replace
                        TextSpan inlineSpan = GetInlineReplaceSpan(resultItem, out absoluteStartIndex, out absoluteLength);

                        string path = resultItem.SourceItem.GetFullPath();
                        if (RDTManager.IsFileOpen(path) && RDTManager.IsFileVisible(path)) // file is open
                        {
                            if (!buffersCache.ContainsKey(path))                           // file's buffer is not yet loaded
                            // load buffer
                            {
                                IVsTextLines textLines = DocumentViewsManager.GetTextLinesForFile(path, false);
                                buffersCache.Add(path, textLines);

                                IOleUndoManager m;
                                // load undo manager
                                int hr = textLines.GetUndoManager(out m);
                                Marshal.ThrowExceptionForHR(hr);
                                undoManagersCache.Add(path, m);
                            }

                            // replace the result item with the new text
                            int h = buffersCache[path].ReplaceLines(inlineSpan.iStartLine, inlineSpan.iStartIndex, inlineSpan.iEndLine, inlineSpan.iEndIndex,
                                                                    Marshal.StringToBSTR(text), text.Length, new TextSpan[] { inlineSpan });
                            Marshal.ThrowExceptionForHR(h);

                            // previous step caused undo unit to be added - remove it
                            List <IOleUndoUnit> units = undoManagersCache[path].RemoveTopFromUndoStack(1);

                            // and add custom undo unit which includes whole operation
                            AbstractUndoUnit newUnit = GetUndoUnit(resultItem, externalChange);
                            newUnit.AppendUnits.AddRange(units);
                            undoManagersCache[path].Add(newUnit);
                        }
                        else
                        {
                            if (!filesCache.ContainsKey(path))   // file is not yet loaded
                            // load the file and save it in cache
                            {
                                filesCache.Add(path, new StringBuilder(File.ReadAllText(path)));
                            }
                            StringBuilder b = filesCache[path];

                            // replace the text
                            b = b.Remove(absoluteStartIndex, absoluteLength);
                            b = b.Insert(absoluteStartIndex, text);
                            filesCache[path] = b;
                        }
                    }
                } catch (Exception ex) {
                    errorRows++;
                    VLOutputWindow.VisualLocalizerPane.WriteException(ex);
                }
            }

            foreach (var pair in filesCache)
            {
                if (RDTManager.IsFileOpen(pair.Key))
                {
                    RDTManager.SetIgnoreFileChanges(pair.Key, true);
                    File.WriteAllText(pair.Key, pair.Value.ToString());
                    RDTManager.SetIgnoreFileChanges(pair.Key, false);
                    RDTManager.SilentlyReloadFile(pair.Key);
                }
                else
                {
                    File.WriteAllText(pair.Key, pair.Value.ToString());
                }
            }
            if (errorRows > 0)
            {
                throw new Exception("Error occured while processing some rows - see Output window for details.");
            }
        }