Exemplo n.º 1
0
        /// <summary>
        /// 获取选中行
        /// </summary>
        /// <returns></returns>
        public string GetSelectedLines()
        {
            TextSelection selectedText = _dte.ActiveDocument.Selection as TextSelection;
            TextPoint     topPoint     = selectedText.TopPoint;
            EditPoint     bottomPoint  = selectedText.BottomPoint.CreateEditPoint();

            return(bottomPoint.GetLines(topPoint.Line, bottomPoint.Line + 1));
        }
Exemplo n.º 2
0
        public string GetCode(out TextPoint startPoint)
        {
            var       range     = this.GetCodeRange();
            EditPoint startEdit = range.Item1.CreateEditPoint();
            string    result    = startEdit.GetLines(startEdit.Line, range.Item2.Line + 1);

            startPoint = startEdit;
            return(result);
        }
        public void IndexGetterTests()
        {
            CSharpHardCodedString hcs = new CSharpHardCodedString(this.codeFile, 349, 362);
            TextDocument          doc = ((EnvDTE.TextDocument) this.codeFile.Document.Object(null));
            EditPoint             ep  = doc.StartPoint.CreateEditPoint();
            string text = ep.GetLines(17, 18);

            Assert.AreEqual(text.IndexOf("\"Test\\\"\\\"\\n\\t\""), hcs.StartIndex);
            Assert.AreEqual(15, hcs.StartingLine);
        }
Exemplo n.º 4
0
        public void IndexGetterTests()
        {
            VBHardCodedString hcs  = new VBHardCodedString(this.codeFile, 157, 172);
            TextDocument      doc  = ((EnvDTE.TextDocument) this.codeFile.Document.Object(null));
            EditPoint         ep   = doc.StartPoint.CreateEditPoint();
            string            text = ep.GetLines(9, 10);

            Assert.AreEqual(text.IndexOf("\"Test Instance\""), hcs.StartIndex);
            Assert.AreEqual(text.IndexOf("\"Test Instance\"") + "\"Test Instance\"".Length, hcs.EndIndex);
            Assert.AreEqual(8, hcs.StartingLine);
        }
Exemplo n.º 5
0
        internal static void InsertBlankLineAfterPoint(EditPoint point)
        {
            if (point.AtEndOfDocument) return;

            point.LineDown(1);
            point.StartOfLine();

            string text = point.GetLines(point.Line, point.Line + 1);
            if (Regex.IsMatch(text, @"^\s*[^\s\}]"))
            {
                point.Insert(Environment.NewLine);
            }
        }
Exemplo n.º 6
0
        public string GetCurrentWord()
        {
            var selectedText = _dte.ActiveDocument.Selection as TextSelection;

            if (selectedText != null)
            {
                EditPoint topPoint    = selectedText.TopPoint.CreateEditPoint();
                string    currentLine = topPoint.GetLines(topPoint.Line, topPoint.Line + 1);

                if (IsBlank(currentLine))
                {
                    return(string.Empty);
                }

                string result;
                int    charIndex = topPoint.LineCharOffset - 1;

                if (topPoint.AtStartOfLine ||
                    (!char.IsWhiteSpace(currentLine[charIndex]) && char.IsWhiteSpace(currentLine[charIndex - 1])))
                {
                    EditPoint rightPoint = topPoint.CreateEditPoint();
                    rightPoint.WordRight();
                    result = currentLine.Substring(topPoint.LineCharOffset - 1,
                                                   rightPoint.LineCharOffset - topPoint.LineCharOffset).Trim();
                }
                else if (topPoint.AtEndOfLine ||
                         (!char.IsWhiteSpace(currentLine[charIndex - 1]) && char.IsWhiteSpace(currentLine[charIndex])))
                {
                    EditPoint leftPoint = topPoint.CreateEditPoint();
                    leftPoint.WordLeft();
                    result = currentLine.Substring(leftPoint.LineCharOffset - 1,
                                                   topPoint.LineCharOffset - leftPoint.LineCharOffset).Trim();
                }
                else if (char.IsLetterOrDigit(currentLine[charIndex - 1]) &&
                         char.IsLetterOrDigit(currentLine[charIndex + 1]))
                {
                    topPoint.WordLeft();
                    EditPoint rightPoint = topPoint.CreateEditPoint();
                    rightPoint.WordRight();
                    result = currentLine.Substring(topPoint.LineCharOffset - 1,
                                                   rightPoint.LineCharOffset - topPoint.LineCharOffset);
                }
                else
                {
                    result = GetSelectedText();
                }

                return(result);
            }
            return(string.Empty);
        }
Exemplo n.º 7
0
        internal static void InsertBlankLineBeforePoint(EditPoint point)
        {
            if (point.Line <= 1) return;

            point.LineUp(1);
            point.StartOfLine();

            string text = point.GetLines(point.Line, point.Line + 1);
            if (Regex.IsMatch(text, @"^\s*[^\s\{]"))
            {
                point.EndOfLine();
                point.Insert(Environment.NewLine);
            }
        }
Exemplo n.º 8
0
        private void ReadModelines(TextDocument td, Settings settings)
        {
            int totalLines = td.EndPoint.Line - td.StartPoint.Line + 1;
            int readLines  = totalLines > kMaxLines ? kMaxLines : totalLines;

            EditPoint ep   = td.StartPoint.CreateEditPoint();
            string    text = ep.GetLines(1, readLines);

            string[] lines = text.Split(new[] { '\r', '\n' });
            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i].Trim();
                DetectVimModeline(settings, line);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// 获取触发行的代码
        /// </summary>
        /// <param name="dte"></param>
        /// <returns></returns>
        public static string GetSelectRowCode(DTE2 dte)
        {
            // 触发内容
            var selection = (TextSelection)dte.ActiveDocument.Selection;

            // 触发起始点
            EditPoint editPoint = selection.AnchorPoint.CreateEditPoint();

            // 选中触发行
            string code = editPoint.GetLines(editPoint.Line, editPoint.Line + 1);

            // 多行转成一行
            code = Regex.Replace(code, @"\s+", s => " ");

            return(code.Trim());
        }
Exemplo n.º 10
0
        /// <summary>
        /// Checks the document in the window for preprocessor directives.
        /// </summary>
        /// <param name="ideWindow">The window of the document to check.</param>
        /// <returns>True if there are preprocessor directives present.</returns>
        private bool CheckForPreprocessorDirectives(EnvDTE.Window ideWindow)
        {
            TextDocument doc       = (TextDocument)ideWindow.Document.Object("TextDocument");
            EditPoint    editPoint = doc.CreateEditPoint(doc.StartPoint);

            while (!editPoint.AtEndOfDocument)
            {
                if (editPoint.GetLines(editPoint.Line, editPoint.Line + 1).StartsWith("#"))
                {
                    return(true);
                }

                editPoint.LineDown(1);
            }

            return(false);
        }
Exemplo n.º 11
0
        public EditedLine GetEditedLine()
        {
            TextSelection textSelection = _document.Selection;

            if (!String.IsNullOrEmpty(textSelection.Text))
            {
                return(new EditedLine(textSelection.Text, 0));
            }

            VirtualPoint point     = textSelection.ActivePoint;
            EditPoint    editPoint = point.CreateEditPoint();

            string line  = editPoint.GetLines(point.Line, point.Line + 1);
            int    caret = point.LineCharOffset - 1;

            return(new EditedLine(line, caret));
        }
Exemplo n.º 12
0
        private Tuple <TextPoint, TextPoint> GetCodeRange()
        {
            // The C# and VB code models don't return comments with vsCMPartWholeWithAttributes
            // (even though some of the member types have Comment and DocComment properties
            // and the code model's RemoveMember will remove the comments).  So we have to
            // grab any attached comment lines manually.
            TextPoint startPoint = this.element.GetStartPoint(vsCMPart.vsCMPartWholeWithAttributes);
            TextPoint endPoint   = this.element.GetEndPoint(vsCMPart.vsCMPartWholeWithAttributes);
            Regex     commentRegex;

            switch (this.language)
            {
            case Language.CSharp:
                // Look for lines starting with optional whitespace followed by //, /*, */, or *.
                commentRegex = new Regex(@"^\s*(//|/\*|\*/|\*)");
                break;

            case Language.VB:
                // Look for lines starting with optional whitespace followed by '.
                commentRegex = new Regex(@"^\s*'");
                break;

            default:
                throw new NotSupportedException("Unsupported language: " + this.language);
            }

            EditPoint startEdit = startPoint.CreateEditPoint();

            startEdit.LineUp();
            while (!startEdit.AtStartOfDocument &&
                   commentRegex.IsMatch(startEdit.GetLines(startEdit.Line, startEdit.Line + 1)))
            {
                startEdit.LineUp();
                startEdit.StartOfLine();
            }

            startEdit.LineDown();
            startEdit.StartOfLine();

            Tuple <TextPoint, TextPoint> result = Tuple.Create((TextPoint)startEdit, endPoint);

            return(result);
        }
        private static void SelectInnerDefinition(TextSelection selection, TextDocument document)
        {
            EditPoint pt = document.CreateEditPoint();

            int startPos    = selection.ActivePoint.Line;
            int currentLine = startPos;

            bool IsCssRule(int lineNum)
            {
                string line = pt.GetLines(lineNum, lineNum + 1);

                // We reached the edge of element styles definition.
                if (line.Contains('}') || line.Contains('{'))
                {
                    return(false);
                }

                // Current line does not contain any CSS rules, break to support invalid/incomplete files.
                if (!line.Contains(':'))
                {
                    return(false);
                }

                return(true);
            }

            // Find the start of styles definition block.
            while (IsCssRule(currentLine) && currentLine-- > 0)
            {
                ;
            }

            selection.MoveToLineAndOffset(currentLine + 1, 1, false);
            currentLine = startPos;

            // Find the end of styles definition block.
            while (IsCssRule(currentLine) && ++currentLine < document.EndPoint.Line)
            {
                ;
            }

            selection.MoveToLineAndOffset(currentLine, 1, true);
        }
Exemplo n.º 14
0
        /// <summary>
        /// 获取触发行的代码
        /// </summary>
        /// <param name="dte"></param>
        /// <returns></returns>
        public static string GetSelection(DTE2 dte)
        {
            // 触发内容
            var    selection = (TextSelection)dte.ActiveDocument.Selection;
            string code      = selection.Text;

            // 没有选中内容则获取当前行代码
            if (string.IsNullOrEmpty(code))
            {
                // 触发起始点
                EditPoint editPoint = selection.AnchorPoint.CreateEditPoint();

                // 选中触发行
                code = editPoint.GetLines(editPoint.Line, editPoint.Line + 1);
            }

            // 多行转成一行
            code = Regex.Replace(code, @"\s+", s => " ");

            return(code.Trim());
        }
Exemplo n.º 15
0
 /// <summary>
 /// Gets the text for the line where the edit point is located.
 /// </summary>
 /// <param name="editPoint">The edit point.</param>
 /// <returns>The text of the edit point's line.</returns>
 internal static string GetLine(this EditPoint editPoint)
 {
     return(editPoint.GetLines(editPoint.Line, editPoint.Line + 1));
 }
Exemplo n.º 16
0
        private void inspectCurrentCppFile(out string functionOfInterest, out string curCodeLine)
        {
            // get the currently active document from the IDE
            Document     doc  = dte.ActiveDocument;
            TextDocument tdoc = doc.Object("TextDocument") as TextDocument;

            if (tdoc == null)
            {
                throw new Exception("Could not obtain the active TextDocument object");
            }

            // do we want a line found in a previous run?
            if (_lastCodeLine != null)
            {
                functionOfInterest      = _lastFunctionOfInterest;
                _lastFunctionOfInterest = null;
                curCodeLine             = _lastCodeLine;
                _lastCodeLine           = null;

                // don't exit if we are still in some header file
                if (!currentFileIsHeaderFile())
                {
                    return;
                }
            }

            // find suitable code line near the cursor
            // TODO: comments are removed when preprocessing and thus can't find a line with comments
            TextSelection selection = tdoc.Selection;
            int           line      = selection.TopPoint.Line;
            EditPoint     editPoint = tdoc.CreateEditPoint();

            curCodeLine = editPoint.GetLines(line, line + 1);

            if (string.IsNullOrWhiteSpace(curCodeLine))
            {
                ++line;
                curCodeLine = editPoint.GetLines(line, line + 1);
                if (string.IsNullOrWhiteSpace(curCodeLine))
                {
                    line       -= 2;
                    curCodeLine = editPoint.GetLines(line, line + 1);
                    if (string.IsNullOrWhiteSpace(curCodeLine))
                    {
                        throw new Exception("Choose a distinctive line of code inside a function or the function definition itself.");
                    }
                }
                selection.GotoLine(line, true);
            }

            // get currently viewed function
            functionOfInterest = "";
            CodeElement codeEl = selection.TopPoint.CodeElement[vsCMElement.vsCMElementFunction];

            if (codeEl != null)
            {
                functionOfInterest = codeEl.FullName;
            }
            else
            {
                dte.StatusBar.Text = "Warning: could not get function object from the IDE.";
                dte.StatusBar.Highlight(true);
            }

            // TODO: in case of a template this gets something like funcName<T>, the assembly contains funcName<actualType>
            //       it doesn't in the case of macros either, e.g. gets _tmain but in the asm it will be wmain

            // now that we extracted the function of interest handle the header file case
            if (currentFileIsHeaderFile() && !trySwitchToCppFile())
            {
                _lastFunctionOfInterest = functionOfInterest;
                _lastCodeLine           = curCodeLine;

                throw new Exception("Please open a cpp file calling this code and re-run.");
            }
        }
Exemplo n.º 17
0
        public void Remove()
        {
            Tuple <TextPoint, TextPoint> range = null;

            try
            {
                // To use RemoveMember, we'd have to cast to CodeClass, CodeStruct, CodeInterface, or CodeEnum.
                // However, RemoveMember won't remove a leading comment other than a DocComment,
                // and in VB RemoveMember doesn't remove the whitespace line after the member.
                // So to make our Remove consistent with GetCode, we'll use GetCodeRange and Delete.
                range = this.GetCodeRange();
            }
            catch (ArgumentException ex)
            {
                // In VS 2015 Update 2, an ArgumentException can occur while removing members with explicitly
                // implemented interface member names if the same named non-explicitly implemented member
                // was just removed.  The Roslyn code model seems to get out of sync on the explicit members,
                // and we have to look them back up to remove them.  This happens, for example, on the second
                // GetEnumerator when sorting these lines (from DictionarySet.cs):
                //      public IEnumerator<T> GetEnumerator() { throw new NotImplementedException(); }
                //      bool ISet< T >.Add(T item) { throw new NotImplementedException(); }
                //      IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
                bool rethrow = this.element.InfoLocation != vsCMInfoLocation.vsCMInfoLocationProject;
                if (!rethrow)
                {
                    ProjectItem    projectItem = this.element.ProjectItem;
                    FileCodeModel2 codeModel   = (FileCodeModel2)projectItem.FileCodeModel;
                    codeModel.Synchronize();
                    this.element = MemberSorter.FindMember(codeModel.CodeElements, this.Name);
                    if (this.element == null)
                    {
                        rethrow = true;
                    }
                    else
                    {
                        range = this.GetCodeRange();
                    }
                }

                if (rethrow)
                {
                    throw new ArgumentException($"Unable to remove or reorder element {this.Name} due to VS FileCodeModel2 limitations.", ex);
                }
            }

            if (range != null)
            {
                EditPoint startEdit = range.Item1.CreateEditPoint();
                startEdit.StartOfLine();

                EditPoint endEdit = range.Item2.CreateEditPoint();
                endEdit.LineDown();
                if (endEdit.GetLines(endEdit.Line, endEdit.Line + 1).Trim().Length == 0)
                {
                    endEdit.LineDown();
                }

                endEdit.StartOfLine();
                startEdit.Delete(endEdit);
            }
        }
Exemplo n.º 18
0
        protected void onPaneUpdated(OutputWindowPane pane)
        {
            if (pane == null || pane.Guid == null)
            {
                return;
            }

            TextDocument textD;

            try {
                textD = pane.TextDocument;
            }
            catch (System.Runtime.InteropServices.COMException ex) {
                Log.Debug("notifyRaw: COMException - '{0}'", ex.Message);
                return;
            }

            int countLines = textD.EndPoint.Line;

            if (countLines <= 1 || countLines - getPrevCountLines(pane.Guid) < 1)
            {
                return;
            }

            if (!dataList.ContainsKey(pane.Guid))
            {
                dataList[pane.Guid] = new ConcurrentQueue <string>();
            }

            EditPoint point = textD.StartPoint.CreateEditPoint();

            // text between Start (inclusive) and ExclusiveEnd (exclusive)
            dataList[pane.Guid].Enqueue(point.GetLines(getPrevCountLines(pane.Guid), countLines)); // e.g. first line: 1, 2
            setPrevCountLines(countLines, pane.Guid);

            //TODO: fix me. Prevent Duplicate Data / bug with OutputWindowPane
            if (tUpdated == null || tUpdated.ThreadState == ThreadState.Unstarted || tUpdated.ThreadState == ThreadState.Stopped)
            {
                tUpdated = new System.Threading.Thread(() =>
                {
                    if (pane == null)
                    {
                        return;
                    }

                    try {
                        notifyRaw(pane.Guid, pane.Name);
                    }
                    catch (Exception ex) {
                        Log.Debug("notifyRaw: failed '{0}'", ex.Message);
                    }
                });

                try {
                    tUpdated.Start();
                }
                catch (Exception ex) {
                    // ThreadStateException, OutOfMemoryException
                    Log.Debug("notifyRaw: can't start '{0}'", ex.Message);
                }
            }
        }
        private void ToggleCommentsAboveMember(EditPoint editPoint, string commentPrefix)
        {
            try {
                int? firstLineOfComment = null;
                editPoint.StartOfLine();
                editPoint.CharLeft();
                while(!editPoint.AtStartOfDocument) {
                    String line = editPoint.GetLines(editPoint.Line, editPoint.Line + 1).Trim();
                    if(line.Length == 0 || line.StartsWith(commentPrefix)) {
                        if(line.Length > 0) {
                            firstLineOfComment = editPoint.Line;
                        } else if(firstLineOfComment.HasValue) {
                            ToggleExpansionAtLine(editPoint.CreateEditPoint(), firstLineOfComment.Value, commentPrefix);
                            firstLineOfComment = null;
                        }

                        editPoint.StartOfLine();
                        editPoint.CharLeft();
                    } else {
                        break;
                    }

                }

                if(firstLineOfComment.HasValue) {
                    ToggleExpansionAtLine(editPoint.CreateEditPoint(), firstLineOfComment.Value, commentPrefix);
                }

            }
            catch(Exception) { }
        }
Exemplo n.º 20
0
        protected int ShowEventHandler(string document, string codeBehind, string codeBehindFile, string className, string objectTypeName, string eventName, string eventHandlerName)
        {
            var projectItem = GetProjectItem(document, codeBehind, codeBehindFile);

            var binder = GetBinder(projectItem);

            if (binder == null)
            {
                return(NativeMethods.E_FAIL);
            }

            projectItem.Open(EnvDTE.Constants.vsViewKindCode);

            var function = binder.FindEventHandler(className, objectTypeName, eventName, eventHandlerName);

            if (function != null)
            {
                bool      prevLineIsEmpty = true;
                EditPoint point           = function.EndPoint.CreateEditPoint();
                point.LineUp(1);
                string lines = point.GetLines(point.Line, (int)(point.Line + 1));
                for (int i = 0; i < lines.Length; i++)
                {
                    if (!char.IsWhiteSpace(lines[i]))
                    {
                        prevLineIsEmpty = false;
                        break;
                    }
                }

                Document document2 = projectItem.Document;
                if (document2 != null)
                {
                    Window activeWindow = document2.ActiveWindow;
                    if (activeWindow != null)
                    {
                        TextSelection selection = activeWindow.Selection as TextSelection;
                        if (selection != null)
                        {
                            selection.MoveToPoint(function.EndPoint, false);
                            if (prevLineIsEmpty)
                            {
                                selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false);
                                int virtualCharOffset = selection.AnchorPoint.VirtualCharOffset;
                                selection.LineUp(false, 1);
                                if (selection.AnchorPoint.VirtualCharOffset <= virtualCharOffset)
                                {
                                    int          indentSize = 4;
                                    TextDocument document3  = document2 as TextDocument;
                                    if (document3 != null)
                                    {
                                        indentSize = document3.IndentSize;
                                    }
                                    selection.MoveToLineAndOffset(selection.AnchorPoint.Line, (int)(virtualCharOffset + indentSize), false);
                                }
                            }
                            else
                            {
                                selection.LineUp(false, 1);
                                //selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, false);
                                selection.EndOfLine(false);
                            }
                        }
                    }
                }
            }

            return(NativeMethods.S_OK);
        }
Exemplo n.º 21
0
        // 1: show assembly code for currently open source file
        // 2: show preprocessed source code
        private void showCppOutput(int mode = 1)
        {
            // if in a header try to open the cpp file
            switchToCppFile();

            // get the currently active document from the IDE
            Document     doc  = dte.ActiveDocument;
            TextDocument tdoc = doc.Object("TextDocument") as TextDocument;

            if (tdoc == null)
            {
                package.showMsgBox("Could not obtain the active TextDocument object");
                return;
            }

            // get currently viewed function
            string        functionOfInterest = "";
            TextSelection selection          = tdoc.Selection;
            CodeElement   codeEl             = selection.ActivePoint.CodeElement[vsCMElement.vsCMElementFunction];

            if (codeEl == null)
            {
                dte.StatusBar.Text = "You should place the cursor inside a function.";
                dte.StatusBar.Highlight(true);
            }
            else
            {
                functionOfInterest = codeEl.FullName;
            }
            // TODO: in case of a template this gets something like funcName<T>, the assembly contains funcName<actualType>
            //       it doesn't in the case of macros either, e.g. gets _tmain but in the asm it will be wmain

            // http://www.viva64.com/en/a/0082/#ID0ELOBK
            // EditPoint directly manipulates text buffer data instead of operating with the text through the editor UI.
            int       line        = selection.ActivePoint.Line;
            EditPoint editPoint   = tdoc.CreateEditPoint();
            string    curCodeLine = editPoint.GetLines(line, line + 1);
            // TODO: comments are removed when preprocessing and thus can't find a line with comments

            // get current configuration
            Project proj             = doc.ProjectItem.ContainingProject;
            ConfigurationManager mgr = proj.ConfigurationManager;
            string platform          = mgr.ActiveConfiguration.PlatformName;
            string conf = mgr.ActiveConfiguration.ConfigurationName;

            // find the currently active configuration for the current file
            // don't use SolutionBuild as there may be mixed platforms
            // use late binding for version independence
            dynamic file        = doc.ProjectItem.Object;                             // as VCFile
            dynamic fileconfigs = file.FileConfigurations;                            // as IVCCollection
            dynamic fileconfig  = fileconfigs.Item(conf + "|" + platform);            // as VCFileConfiguration
            dynamic tool        = fileconfig.Tool;                                    // VCCLCompilerTool


            // save original settings to restore them later

            // there seems to be no better way
            // DTE undo contexts doesn't cover these project settings
            // unload/reload the project may close all open files
            // manipulating proj.Saved or .IsDirty does not work
            bool    lto             = tool.WholeProgramOptimization;
            dynamic asmtype         = tool.AssemblerOutput;
            dynamic genPreprocessed = tool.GeneratePreprocessedFile;
            string  asmloc          = tool.AssemblerListingLocation;
            string  objFileLocation = tool.ObjectFile;

            string generatedFile;

            if (mode == 1)
            {
                // asmListingAsmSrc => '.asm'
                generatedFile = Path.GetTempFileName() + ".asm";                 //System.IO.Path.GetTempPath

                tool.WholeProgramOptimization = false;
                tool.AssemblerOutput          = (dynamic)Enum.Parse(tool.AssemblerOutput.GetType(), "asmListingAsmSrc");
                tool.AssemblerListingLocation = generatedFile;
            }
            else             /*if (mode == 2)*/
            {
                // not generally applicable
                //generatedFile = prj.ProjectDirectory + prjconfig.IntermediateDirectory + Replace(file.Name, ".cpp", ".i");
                generatedFile = Path.GetTempFileName() + ".cpp";

                tool.GeneratePreprocessedFile = (dynamic)Enum.Parse(tool.GeneratePreprocessedFile.GetType(), "preprocessYes");
                // there's no separate option for this, so misuse /Fo
                tool.ObjectFile = generatedFile;
            }

            try
            {
                // forceBuild (even if up-to-date) and waitOnBuild
                fileconfig.Compile(true, true);
            }
            catch (Exception e)
            {
                package.writeStatus($"VCFileConfiguration.Compile() failed: {e.Message}. Trying command Build.Compile now...");

                _dispBuildEvents_OnBuildProjConfigDoneEventHandler onProjBuildDone = null;
                onProjBuildDone = (project, projectConfig, platfrm, solutionConfig, success) =>
                {
                    dte.Events.BuildEvents.OnBuildProjConfigDone -= onProjBuildDone;
                    // naive cleanup
                    if (mode == 1)
                    {
                        tool.WholeProgramOptimization = lto;
                        tool.AssemblerOutput          = asmtype;
                        tool.AssemblerListingLocation = asmloc;
                    }
                    else if (mode == 2)
                    {
                        tool.GeneratePreprocessedFile = genPreprocessed;
                        tool.ObjectFile = objFileLocation;
                    }

                    if (success)
                    {
                        postCompileCpp(generatedFile, mode, functionOfInterest, curCodeLine);
                    }
                };
                dte.Events.BuildEvents.OnBuildProjConfigDone += onProjBuildDone;
                dte.ExecuteCommand("Build.Compile");
                return;
            }

            // naive cleanup
            if (mode == 1)
            {
                tool.WholeProgramOptimization = lto;
                tool.AssemblerOutput          = asmtype;
                tool.AssemblerListingLocation = asmloc;
            }
            else if (mode == 2)
            {
                tool.GeneratePreprocessedFile = genPreprocessed;
                tool.ObjectFile = objFileLocation;
            }

            postCompileCpp(generatedFile, mode, functionOfInterest, curCodeLine);
        }
        /// <summary>Parses for strings by iterating through the FileCodeModel.</summary>
        /// <param name="startPoint">The start point.</param>
        /// <param name="endPoint">The end point.</param>
        /// <param name="lastDocumentLength">Last length of the document.</param>
        private void ParseForStrings(TextPoint startPoint,
                                     TextPoint endPoint,
                                     int lastDocumentLength)
        {
            //0.35-0.06 seconds (threaded: 2.47-1.77 seconds)
            List <StringResource> stringResources = new List <StringResource>();

            bool isFullDocument          = startPoint.AtStartOfDocument && endPoint.AtEndOfDocument,
                 isTextWithStringLiteral = true;
            int startLine      = startPoint.Line,
                startCol       = startPoint.LineCharOffset,
                endLine        = endPoint.Line,
                endCol         = endPoint.LineCharOffset,
                documentLength = endPoint.Parent.EndPoint.Line,
                insertIndex    = 0;

            if (isFullDocument)
            {
                m_StringResources.Clear();
            }
            else
            {
                #region document manipulated -> adapt string resources and locations

                //determine whether the text between startLine and endLine (including) contains double quotes
                EditPoint editPoint = startPoint.CreateEditPoint() as EditPoint2;
                if (!startPoint.AtStartOfLine)
                {
                    editPoint.StartOfLine();
                }
                isTextWithStringLiteral = editPoint.GetLines(startLine, endLine + 1).Contains("\"");

                //move trailing locations behind changed lines if needed and
                //remove string resources on changed lines

                int lineOffset = documentLength - lastDocumentLength;
#if DEBUG_OUTPUT
                System.Diagnostics.Debug.Print("  Line offset is {0}", lineOffset);
#endif

                for (int i = m_StringResources.Count - 1; i >= 0; --i)
                {
                    StringResource stringResource = m_StringResources[i];
                    int            lineNo         = stringResource.Location.X;

                    if (lineNo + lineOffset > endLine)
                    {
                        if (lineOffset != 0)
                        {
#if DEBUG_OUTPUT
                            System.Diagnostics.Debug.Print("  Move string literal from line {0} to {1}", lineNo, lineNo + lineOffset);
#endif
                            stringResource.Offset(lineOffset, 0); //move
                        } //if
                    }
                    else if (lineNo >= startLine)
                    {
#if DEBUG_OUTPUT
                        System.Diagnostics.Debug.Print("  Remove string literal {0} ({1}): {2}", i, stringResource.Location, stringResource.Text);
#endif
                        m_StringResources.RemoveAt(i); //remove changed line
                    }
                    else if (insertIndex == 0)
                    {
#if DEBUG_OUTPUT
                        System.Diagnostics.Debug.Print("  List insert index is {0} / {1}", i + 1, m_StringResources.Count - 1);
#endif
                        insertIndex = i + 1;
                    } //else if
                }     //for

                #endregion
            } //else

#if DEBUG_OUTPUT
            System.Diagnostics.Debug.Print("  Text has{0} string literals.", isTextWithStringLiteral ? string.Empty : " no");
#endif

            if (isTextWithStringLiteral)
            {
                CodeElements elements = m_Window.Document.ProjectItem.FileCodeModel.CodeElements;

                foreach (CodeElement element in elements)
                {
                    ParseForStrings(element, m_DoProgress, stringResources, m_Settings, m_IsCSharp, startLine, endLine);

#if DEBUG
                    if (element.Kind == vsCMElement.vsCMElementProperty)
                    {
                        CodeProperty prop = element as CodeProperty;

                        if ((prop.Getter == null) && (prop.Setter == null))
                        {
                            //here we have an expression bodied property
                            //if (m_IVsTextView != null)
                            //{
                            //  m_IVsTextView.
                            //}
                        }
                    }
#endif
                } //foreach

#if DEBUG_OUTPUT
                System.Diagnostics.Debug.Print("  Found {0} string literals", stringResources.Count);
#endif

                if (isFullDocument)
                {
                    m_StringResources.AddRange(stringResources);
                }
                else if (stringResources.Count > 0)
                {
                    m_StringResources.InsertRange(insertIndex, stringResources);
                }
            } //if

            m_DoCompleted(isFullDocument || (stringResources.Count > 0));
        }
        public bool Start()
        {
            try
            {
                if (!ProjectItem.IsOpen)
                {
                    ProjectItem.Open();
                }

                Document     document           = ProjectItem.Document;
                TextDocument textDocument       = document.Object(Constants.TEXT_DOCUMENT) as TextDocument;
                TextPoint    startPoint         = textDocument.StartPoint;
                TextPoint    endPoint           = textDocument.EndPoint;
                int          lastDocumentLength = textDocument.EndPoint.Line;

                logger.Debug("Start - parsing document: " + FileName);

                List <StringResource> stringResources = new List <StringResource>();

                bool isFullDocument          = startPoint.AtStartOfDocument && endPoint.AtEndOfDocument,
                     isTextWithStringLiteral = true;
                int startLine      = startPoint.Line;
                int startCol       = startPoint.LineCharOffset;
                int endLine        = endPoint.Line;
                int endCol         = endPoint.LineCharOffset;
                int documentLength = endPoint.Parent.EndPoint.Line;
                int insertIndex    = 0;

                if (isFullDocument)
                {
                    StringResources.Clear();
                }
                else
                {
                    //determine whether the text between startLine and endLine (including) contains double quotes
                    EditPoint editPoint = startPoint.CreateEditPoint() as EditPoint2;
                    if (!startPoint.AtStartOfLine)
                    {
                        editPoint.StartOfLine();
                    }
                    isTextWithStringLiteral = editPoint.GetLines(startLine, endLine + 1).Contains("\"");

                    //move trailing locations behind changed lines if needed and
                    //remove string resources on changed lines
                    int lineOffset = documentLength - lastDocumentLength;

                    for (int i = StringResources.Count - 1; i >= 0; --i)
                    {
                        StringResource stringResource = StringResources[i];
                        int            lineNo         = stringResource.Location.X;

                        if (lineNo + lineOffset > endLine)
                        {
                            if (lineOffset != 0)
                            {
                                stringResource.Offset(lineOffset, 0); //move
                            }
                        }
                        else if (lineNo >= startLine)
                        {
                            StringResources.RemoveAt(i); //remove changed line
                        }
                        else if (insertIndex == 0)
                        {
                            insertIndex = i + 1;
                        }
                    }
                }

                if (isTextWithStringLiteral)
                {
                    CodeElements elements = ProjectItem.FileCodeModel.CodeElements;

                    foreach (CodeElement element in elements)
                    {
                        ParseForStrings(element, stringResources, isCsharp, m_Settings, startLine, endLine);
                    }

                    if (isFullDocument)
                    {
                        StringResources.AddRange(stringResources);
                    }
                    else if (stringResources.Count > 0)
                    {
                        StringResources.InsertRange(insertIndex, stringResources);
                    }
                }

                logger.Debug("End - parsing document: " + FileName);

                return(true);
            } catch (Exception e)
            {
                logger.Warn(e, "An error occurred while parsing file: " + FileName);
                return(false);
            }
        }