Example #1
0
        public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts)
        {
            if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out var startPos)) &&
                ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out var endPos)))
            {
                var textBuffer = vsTextLines.ToITextBuffer(_services);
                var range      = TextRange.FromBounds(startPos, endPos);

                var snapshot = textBuffer.CurrentSnapshot;
                var point    = snapshot.CreateTrackingPoint(range.End, PointTrackingMode.Positive);
                var text     = snapshot.GetText(range.ToSpan());


                var line     = snapshot.GetLineFromPosition(range.Start);
                var lineTail = snapshot.GetText(Span.FromBounds(range.End, line.End));

                var formatter = new RangeFormatter(_services);
                formatter.FormatRange(TextView.ToEditorView(), textBuffer.ToEditorBuffer(), range);

                // Do not trim whitespace after standalone operators
                if (IsStandaloneOperator(text) && string.IsNullOrEmpty(lineTail))
                {
                    textBuffer.Insert(point.GetPosition(textBuffer.CurrentSnapshot), " ");
                }
            }
            return(VSConstants.S_OK);
        }
Example #2
0
        public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts)
        {
            int hr       = VSConstants.S_OK;
            int startPos = -1;
            int endPos   = -1;

            if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) &&
                ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos)))
            {
                var textBuffer = vsTextLines.ToITextBuffer();
                RangeFormatter.FormatRange(TextView, textBuffer, TextRange.FromBounds(startPos, endPos), REditorSettings.FormatOptions);
            }
            return(hr);
        }
        public static int GetPositionOfLineIndex(this IVsTextLines buffer, int iLine, int iIndex)
        {
            int piPosition;

            buffer.GetPositionOfLineIndex(iLine, iIndex, out piPosition);
            return(piPosition);
        }
Example #4
0
        public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts)
        {
            int hr       = VSConstants.S_OK;
            int startPos = -1;
            int endPos   = -1;

            if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) &&
                ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos)))
            {
                var textBuffer = vsTextLines.ToITextBuffer();
                var range      = TextRange.FromBounds(startPos, endPos);
                // Do not format standalone operators
                var text = textBuffer.CurrentSnapshot.GetText(range.ToSpan());
                if (CanFormat(text))
                {
                    RangeFormatter.FormatRange(TextView, textBuffer, range, VsAppShell.Current.GetService <IREditorSettings>().FormatOptions, VsAppShell.Current);
                }
            }
            return(hr);
        }
Example #5
0
        public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts)
        {
            var startPos = -1;
            var endPos   = -1;

            if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) &&
                ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos)))
            {
                var textBuffer = vsTextLines.ToITextBuffer(_services);
                var range      = TextRange.FromBounds(startPos, endPos);
                // Do not format standalone operators
                var text = textBuffer.CurrentSnapshot.GetText(range.ToSpan());
                if (CanFormat(text))
                {
                    var formatter = new RangeFormatter(_services);
                    formatter.FormatRange(TextView.ToEditorView(), textBuffer.ToEditorBuffer(), range);
                }
            }
            return(VSConstants.S_OK);
        }
        public static List<EditSpan> ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize)
        {
            string filePath = FilePathUtilities.GetFilePath(pBuffer);

            // Return dynamic scanner based on file extension
           
            List<EditSpan> changeList = new List<EditSpan>();
            int nbLines;
            pBuffer.GetLineCount(out nbLines);
            string codeToFormat;

            int lastLine;
            int lastLineIndex;
            pBuffer.GetLastLineIndex(out lastLine, out lastLineIndex);
            pBuffer.GetLineText(0, 0, lastLine, lastLineIndex, out codeToFormat);

            NShaderScanner shaderScanner = NShaderScannerFactory.GetShaderScanner(filePath);
            Scanner lexer = shaderScanner.Lexer;
            lexer.SetSource(codeToFormat, 0);

            int spanStart;
            int spanEnd;
            pBuffer.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex, out spanStart);
            pBuffer.GetPositionOfLineIndex(span.iEndLine, span.iEndIndex, out spanEnd);

            int state = 0;
            int start, end;
            ShaderToken token = (ShaderToken) lexer.GetNext(ref state, out start, out end);

            List<int> brackets = new List<int>();
            List<int> delimiters = new List<int>();
            // !EOL and !EOF
            int level = 0;
            int startCopy = 0;
            int levelParenthesis = 0;
            while (token != ShaderToken.EOF)
            {
                switch (token)
                {
                    case ShaderToken.LEFT_PARENTHESIS:
                        levelParenthesis++;
                        break;
                    case ShaderToken.RIGHT_PARENTHESIS:
                        levelParenthesis--;
                        if ( levelParenthesis < 0 )
                        {
                            levelParenthesis = 0;
                        }
                        break;
                    case ShaderToken.LEFT_BRACKET:
                        level++;
                        if (codeToFormat[start] == '{' && start >= spanStart && end <= spanEnd)
                        {
                            Match match = matchBraceStart.Match(codeToFormat, start);
                            

                            StringBuilder codeFormatted = new StringBuilder();
                            codeFormatted.Append("{\r\n");
                            int levelToIndentNext = level;                            
                            if (match.Groups.Count == 2)
                            {
                                string matchStr = match.Groups[1].Value;
                                levelToIndentNext--;
                            }
                            for (int i = 0; i < levelToIndentNext; i++)
                            {
                                for (int j = 0; j < tabSize; j++)
                                {
                                    codeFormatted.Append(' ');
                                }
                            }
                            if (match.Groups.Count == 2)
                            {
                                codeFormatted.Append("}\r\n");
                            }

                            TextSpan editTextSpan = new TextSpan();

                            pBuffer.GetLineIndexOfPosition(start,
                                                           out editTextSpan.iStartLine,
                                                           out editTextSpan.iStartIndex);
                            pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
                                                           out editTextSpan.iEndLine,
                                                           out editTextSpan.iEndIndex);

                            changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
                        }
                        break;
                    case ShaderToken.RIGHT_BRACKET:
                        level--;
                        if (level < 0)
                        {
                            level = 0;
                        }
                        brackets.Add(start);
                        break;
                    case ShaderToken.DELIMITER:
                        if (codeToFormat[start] == ';' && start >= spanStart && end <= spanEnd && levelParenthesis == 0)
                        {
                            Match match = matchEndOfStatement.Match(codeToFormat, start);

                            StringBuilder codeFormatted = new StringBuilder();
                            codeFormatted.Append(";\r\n");
                            int levelToIndentNext = level;
                            bool isBracketFound = (match.Groups.Count == 2 && match.Groups[1].Value == "}");
                            if (isBracketFound)
                            {
                                string matchStr = match.Groups[1].Value;
                                levelToIndentNext--;
                            }
                            for (int i = 0; i < levelToIndentNext; i++)
                            {
                                for (int j = 0; j < tabSize; j++)
                                {
                                    codeFormatted.Append(' ');
                                }
                            }
                            if (isBracketFound)
                            {
                                codeFormatted.Append("}\r\n");
                            }

                            TextSpan editTextSpan = new TextSpan();

                            pBuffer.GetLineIndexOfPosition(start,
                                                           out editTextSpan.iStartLine,
                                                           out editTextSpan.iStartIndex);
                            pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
                                                           out editTextSpan.iEndLine,
                                                           out editTextSpan.iEndIndex);

                            changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
                        }
                        break;
                }
                token = (ShaderToken) lexer.GetNext(ref state, out start, out end);
            }
            return changeList;
        }
Example #7
0
        public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts)
        {
            MSXML.IXMLDOMNode codeNode, snippetTypes, declarations, imports;

            int hr;

            if (ErrorHandler.Failed(hr = _session.GetSnippetNode("CodeSnippet:Code", out codeNode)))
            {
                return(hr);
            }

            if (ErrorHandler.Failed(hr = _session.GetHeaderNode("CodeSnippet:SnippetTypes", out snippetTypes)))
            {
                return(hr);
            }

            List <string> declList = new List <string>();

            if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Declarations", out declarations)) &&
                declarations != null)
            {
                foreach (MSXML.IXMLDOMNode declType in declarations.childNodes)
                {
                    var id = declType.selectSingleNode("./CodeSnippet:ID");
                    if (id != null)
                    {
                        declList.Add(id.text);
                    }
                }
            }

            List <string> importList = new List <string>();

            if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Imports", out imports)) &&
                imports != null)
            {
                foreach (MSXML.IXMLDOMNode import in imports.childNodes)
                {
                    var id = import.selectSingleNode("./CodeSnippet:Namespace");
                    if (id != null)
                    {
                        importList.Add(id.text);
                    }
                }
            }

            bool surroundsWith = false, surroundsWithStatement = false;

            foreach (MSXML.IXMLDOMNode snippetType in snippetTypes.childNodes)
            {
                if (snippetType.nodeName == "SnippetType")
                {
                    if (snippetType.text == SurroundsWith)
                    {
                        surroundsWith = true;
                    }
                    else if (snippetType.text == SurroundsWithStatement)
                    {
                        surroundsWithStatement = true;
                    }
                }
            }

            // get the indentation of where we're inserting the code...
            string baseIndentation = GetBaseIndentation(ts);
            int    startPosition;

            pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPosition);
            var insertTrackingPoint = _textView.TextBuffer.CurrentSnapshot.CreateTrackingPoint(startPosition, PointTrackingMode.Positive);

            TextSpan?endSpan = null;

            using (var edit = _textView.TextBuffer.CreateEdit()) {
                if (surroundsWith || surroundsWithStatement)
                {
                    // this is super annoyning...  Most languages can do a surround with and $selected$ can be
                    // an empty string and everything's the same.  But in Python we can't just have something like
                    // "while True: " without a pass statement.  So if we start off with an empty selection we
                    // need to insert a pass statement.  This is the purpose of the "SurroundsWithStatement"
                    // snippet type.
                    //
                    // But, to make things even more complicated, we don't have a good indication of what's the
                    // template text vs. what's the selected text.  We do have access to the original template,
                    // but all of the values have been replaced with their default values when we get called
                    // here.  So we need to go back and re-apply the template, except for the $selected$ part.
                    //
                    // Also, the text has \n, but the inserted text has been replaced with the appropriate newline
                    // character for the buffer.
                    var templateText = codeNode.text.Replace("\n", _textView.Options.GetNewLineCharacter());
                    foreach (var decl in declList)
                    {
                        string defaultValue;
                        if (ErrorHandler.Succeeded(_session.GetFieldValue(decl, out defaultValue)))
                        {
                            templateText = templateText.Replace("$" + decl + "$", defaultValue);
                        }
                    }
                    templateText = templateText.Replace("$end$", "");

                    // we can finally figure out where the selected text began witin the original template...
                    int selectedIndex = templateText.IndexOf("$selected$");
                    if (selectedIndex != -1)
                    {
                        var selection = _textView.Selection;

                        // now we need to get the indentation of the $selected$ element within the template,
                        // as we'll need to indent the selected code to that level.
                        string indentation = GetTemplateSelectionIndentation(templateText, selectedIndex);

                        var start = _selectionStart.GetPosition(_textView.TextBuffer.CurrentSnapshot);
                        var end   = _selectionEnd.GetPosition(_textView.TextBuffer.CurrentSnapshot);
                        if (end < start)
                        {
                            // we didn't actually have a selction, and our negative tracking pushed us
                            // back to the start of the buffer...
                            end = start;
                        }
                        var selectedSpan = Span.FromBounds(start, end);

                        if (surroundsWithStatement &&
                            String.IsNullOrWhiteSpace(_textView.TextBuffer.CurrentSnapshot.GetText(selectedSpan)))
                        {
                            // we require a statement here and the user hasn't selected any code to surround,
                            // so we insert a pass statement (and we'll select it after the completion is done)
                            edit.Replace(new Span(startPosition + selectedIndex, end - start), "pass");

                            // Surround With can be invoked with no selection, but on a line with some text.
                            // In that case we need to inject an extra new line.
                            var endLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end);
                            var endText = endLine.GetText().Substring(end - endLine.Start);
                            if (!String.IsNullOrWhiteSpace(endText))
                            {
                                edit.Insert(end, _textView.Options.GetNewLineCharacter());
                            }

                            // we want to leave the pass statement selected so the user can just
                            // continue typing over it...
                            var startLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPosition + selectedIndex);
                            _selectEndSpan = true;
                            endSpan        = new TextSpan()
                            {
                                iStartLine  = startLine.LineNumber,
                                iEndLine    = startLine.LineNumber,
                                iStartIndex = baseIndentation.Length + indentation.Length,
                                iEndIndex   = baseIndentation.Length + indentation.Length + 4,
                            };
                        }

                        IndentSpan(
                            edit,
                            indentation,
                            _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(start).LineNumber + 1, // 1st line is already indented
                            _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end).LineNumber
                            );
                    }
                }

                // we now need to update any code which was not selected  that we just inserted.
                IndentSpan(edit, baseIndentation, ts[0].iStartLine + 1, ts[0].iEndLine);

                edit.Apply();
            }

            if (endSpan != null)
            {
                _session.SetEndSpan(endSpan.Value);
            }

            // add any missing imports...
            AddMissingImports(
                importList,
                insertTrackingPoint.GetPoint(_textView.TextBuffer.CurrentSnapshot)
                ).Wait();

            return(hr);
        }
Example #8
0
        public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) {
            MSXML.IXMLDOMNode codeNode, snippetTypes, declarations, imports;

            int hr;
            if (ErrorHandler.Failed(hr = _session.GetSnippetNode("CodeSnippet:Code", out codeNode))) {
                return hr;
            }

            if (ErrorHandler.Failed(hr = _session.GetHeaderNode("CodeSnippet:SnippetTypes", out snippetTypes))) {
                return hr;
            }

            List<string> declList = new List<string>();
            if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Declarations", out declarations)) 
                && declarations != null) {
                foreach (MSXML.IXMLDOMNode declType in declarations.childNodes) {
                    var id = declType.selectSingleNode("./CodeSnippet:ID");
                    if (id != null) {
                        declList.Add(id.text);
                    }
                }
            }

            List<string> importList = new List<string>();
            if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Imports", out imports)) 
                && imports != null) {
                foreach (MSXML.IXMLDOMNode import in imports.childNodes) {
                    var id = import.selectSingleNode("./CodeSnippet:Namespace");
                    if (id != null) {
                        importList.Add(id.text);
                    }
                }
            }

            bool surroundsWith = false, surroundsWithStatement = false;
            foreach (MSXML.IXMLDOMNode snippetType in snippetTypes.childNodes) {
                if (snippetType.nodeName == "SnippetType") {
                    if (snippetType.text == SurroundsWith) {
                        surroundsWith = true;
                    } else if (snippetType.text == SurroundsWithStatement) {
                        surroundsWithStatement = true;
                    }
                }
            }

            // get the indentation of where we're inserting the code...
            string baseIndentation = GetBaseIndentation(ts);
            int startPosition;
            pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPosition);
            var insertTrackingPoint = _textView.TextBuffer.CurrentSnapshot.CreateTrackingPoint(startPosition, PointTrackingMode.Positive);

            TextSpan? endSpan = null;
            using (var edit = _textView.TextBuffer.CreateEdit()) {
                if (surroundsWith || surroundsWithStatement) {
                    // this is super annoyning...  Most languages can do a surround with and $selected$ can be
                    // an empty string and everything's the same.  But in Python we can't just have something like
                    // "while True: " without a pass statement.  So if we start off with an empty selection we
                    // need to insert a pass statement.  This is the purpose of the "SurroundsWithStatement"
                    // snippet type.
                    //
                    // But, to make things even more complicated, we don't have a good indication of what's the 
                    // template text vs. what's the selected text.  We do have access to the original template,
                    // but all of the values have been replaced with their default values when we get called
                    // here.  So we need to go back and re-apply the template, except for the $selected$ part.
                    //
                    // Also, the text has \n, but the inserted text has been replaced with the appropriate newline
                    // character for the buffer.
                    var templateText = codeNode.text.Replace("\n", _textView.Options.GetNewLineCharacter());
                    foreach (var decl in declList) {
                        string defaultValue;
                        if (ErrorHandler.Succeeded(_session.GetFieldValue(decl, out defaultValue))) {
                            templateText = templateText.Replace("$" + decl + "$", defaultValue);
                        }
                    }
                    templateText = templateText.Replace("$end$", "");

                    // we can finally figure out where the selected text began witin the original template...
                    int selectedIndex = templateText.IndexOf("$selected$");
                    if (selectedIndex != -1) {
                        var selection = _textView.Selection;
                        
                        // now we need to get the indentation of the $selected$ element within the template,
                        // as we'll need to indent the selected code to that level.
                        string indentation = GetTemplateSelectionIndentation(templateText, selectedIndex);

                        var start = _selectionStart.GetPosition(_textView.TextBuffer.CurrentSnapshot);
                        var end = _selectionEnd.GetPosition(_textView.TextBuffer.CurrentSnapshot);
                        if (end < start) {
                            // we didn't actually have a selction, and our negative tracking pushed us
                            // back to the start of the buffer...
                            end = start;
                        }
                        var selectedSpan = Span.FromBounds(start, end);

                        if (surroundsWithStatement && 
                            String.IsNullOrWhiteSpace(_textView.TextBuffer.CurrentSnapshot.GetText(selectedSpan))) {
                            // we require a statement here and the user hasn't selected any code to surround,
                            // so we insert a pass statement (and we'll select it after the completion is done)
                            edit.Replace(new Span(startPosition + selectedIndex, end - start), "pass");

                            // Surround With can be invoked with no selection, but on a line with some text.
                            // In that case we need to inject an extra new line.
                            var endLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end);
                            var endText = endLine.GetText().Substring(end - endLine.Start);
                            if (!String.IsNullOrWhiteSpace(endText)) {
                                edit.Insert(end, _textView.Options.GetNewLineCharacter());
                            }

                            // we want to leave the pass statement selected so the user can just
                            // continue typing over it...
                            var startLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPosition + selectedIndex);                            
                            _selectEndSpan = true;
                            endSpan = new TextSpan() {
                                iStartLine = startLine.LineNumber,
                                iEndLine = startLine.LineNumber,
                                iStartIndex = baseIndentation.Length + indentation.Length,
                                iEndIndex = baseIndentation.Length + indentation.Length + 4,
                            };
                        }

                        IndentSpan(
                            edit, 
                            indentation,
                            _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(start).LineNumber + 1, // 1st line is already indented
                            _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end).LineNumber
                        );
                    }
                }

                // we now need to update any code which was not selected  that we just inserted.
                IndentSpan(edit, baseIndentation, ts[0].iStartLine + 1, ts[0].iEndLine);

                edit.Apply();
            }

            if (endSpan != null) {
                _session.SetEndSpan(endSpan.Value);
            }
            
            // add any missing imports...
            AddMissingImports(
                importList,
                insertTrackingPoint.GetPoint(_textView.TextBuffer.CurrentSnapshot)
            ).Wait();

            return hr;
        }
Example #9
0
 public int GetPositionOfLineIndex(int iLine, int iIndex, out int piPosition)
 {
     return(_textBuffer.GetPositionOfLineIndex(iLine, iIndex, out piPosition));
 }
Example #10
0
        /// <summary>
        /// Format the content inserted by a code snippet
        /// </summary>
        public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts)
        {
            // Example of a snippet template (taken from forprops.snippet and use ... to represent
            // indent spaces):
            //
            // for (var $property$ in $object$) {
            // ....if ($object$.hasOwnProperty($property$)) {
            // ........$selected$$end$
            // ....}
            // };
            //
            // Example of code in pBuffer (the for loop is inserted by a forprops snippet):
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ....if (object.hasOwnProperty(property)) {
            // ........
            // ....}
            // };
            //
            // Result examples:
            //
            // (1) If indent size = 2:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ..if (object.hasOwnProperty(property)) {
            // ....
            // ..}
            // };
            //
            // (2) If indent size = 2 and OpenBracesOnNewLineForControl = true:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object)
            // {
            // ..if (object.hasOwnProperty(property))
            // ..{
            // ....
            // ..}
            // };

            // Algorithm: The idea is to use Formatting.Formatter to format the inserted content.
            // However, Formatting.Formatter does not format lines that only contain spaces. For
            // example, here is how Formatting.Formatter formats the code above:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ..if (object.hasOwnProperty(property)) {
            // ........
            // ..}
            // };
            //
            // An additional step will be included to ensure such lines are formatted correctly.

            int baseIndentationLevel = GetViewIndentationLevelAtLine(ts[0].iStartLine);

            for (int lineNumber = ts[0].iStartLine; lineNumber <= ts[0].iEndLine; ++lineNumber)
            {
                string lineContent = _textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(lineNumber).GetText();

                string indentationString = GetTemplateIndentationString(lineContent);
                if (indentationString != lineContent)   // This means line contains some characters other than spaces
                {
                    continue;
                }

                int newIndentationLevel = baseIndentationLevel + GetTemplateIndentationLevel(indentationString);

                string newIndentation = _textView.Options.IsConvertTabsToSpacesEnabled()
                    ? new string(' ', newIndentationLevel *_textView.Options.GetIndentSize())
                    : new string('\t', newIndentationLevel);

                using (var edit = _textView.TextBuffer.CreateEdit()) {
                    int indendationPos;
                    pBuffer.GetPositionOfLineIndex(lineNumber, 0, out indendationPos);
                    Span bufferIndentationSpan = new Span(indendationPos, indentationString.Length);
                    edit.Replace(bufferIndentationSpan, newIndentation);
                    edit.Apply();
                }
            }

            // Now that we have handled empty lines, use Formatter to format the inserted content.
            int startPos = 0, endPos = 0;

            pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos);
            pBuffer.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos);
            Formatting.FormattingOptions options = EditFilter.CreateFormattingOptions(_textView.Options, _textView.TextBuffer.CurrentSnapshot);
            string text = _textView.TextBuffer.CurrentSnapshot.GetText();

            EditFilter.ApplyEdits(_textView.TextBuffer, Formatting.Formatter.GetEditsForRange(text, startPos, endPos, options));

            return(VSConstants.S_OK);
        }
Example #11
0
        public static List <EditSpan> ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize)
        {
            string filePath = FilePathUtilities.GetFilePath(pBuffer);

            // Return dynamic scanner based on file extension

            List <EditSpan> changeList = new List <EditSpan>();
            int             nbLines;

            pBuffer.GetLineCount(out nbLines);
            string codeToFormat;

            int lastLine;
            int lastLineIndex;

            pBuffer.GetLastLineIndex(out lastLine, out lastLineIndex);
            pBuffer.GetLineText(0, 0, lastLine, lastLineIndex, out codeToFormat);

            NShaderScanner shaderScanner = NShaderScannerFactory.GetShaderScanner(filePath);
            Scanner        lexer         = shaderScanner.Lexer;

            lexer.SetSource(codeToFormat, 0);

            int spanStart;
            int spanEnd;

            pBuffer.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex, out spanStart);
            pBuffer.GetPositionOfLineIndex(span.iEndLine, span.iEndIndex, out spanEnd);

            int         state = 0;
            int         start, end;
            ShaderToken token = (ShaderToken)lexer.GetNext(ref state, out start, out end);

            List <int> brackets   = new List <int>();
            List <int> delimiters = new List <int>();
            // !EOL and !EOF
            int level            = 0;
            int startCopy        = 0;
            int levelParenthesis = 0;

            while (token != ShaderToken.EOF)
            {
                switch (token)
                {
                case ShaderToken.LEFT_PARENTHESIS:
                    levelParenthesis++;
                    break;

                case ShaderToken.RIGHT_PARENTHESIS:
                    levelParenthesis--;
                    if (levelParenthesis < 0)
                    {
                        levelParenthesis = 0;
                    }
                    break;

                case ShaderToken.LEFT_BRACKET:
                    level++;
                    if (codeToFormat[start] == '{' && start >= spanStart && end <= spanEnd)
                    {
                        Match match = matchBraceStart.Match(codeToFormat, start);


                        StringBuilder codeFormatted = new StringBuilder();
                        codeFormatted.Append("{\r\n");
                        int levelToIndentNext = level;
                        if (match.Groups.Count == 2)
                        {
                            string matchStr = match.Groups[1].Value;
                            levelToIndentNext--;
                        }
                        for (int i = 0; i < levelToIndentNext; i++)
                        {
                            for (int j = 0; j < tabSize; j++)
                            {
                                codeFormatted.Append(' ');
                            }
                        }
                        if (match.Groups.Count == 2)
                        {
                            codeFormatted.Append("}\r\n");
                        }

                        TextSpan editTextSpan = new TextSpan();

                        pBuffer.GetLineIndexOfPosition(start,
                                                       out editTextSpan.iStartLine,
                                                       out editTextSpan.iStartIndex);
                        pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
                                                       out editTextSpan.iEndLine,
                                                       out editTextSpan.iEndIndex);

                        changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
                    }
                    break;

                case ShaderToken.RIGHT_BRACKET:
                    level--;
                    if (level < 0)
                    {
                        level = 0;
                    }
                    brackets.Add(start);
                    break;

                case ShaderToken.DELIMITER:
                    if (codeToFormat[start] == ';' && start >= spanStart && end <= spanEnd && levelParenthesis == 0)
                    {
                        Match match = matchEndOfStatement.Match(codeToFormat, start);

                        StringBuilder codeFormatted = new StringBuilder();
                        codeFormatted.Append(";\r\n");
                        int  levelToIndentNext = level;
                        bool isBracketFound    = (match.Groups.Count == 2 && match.Groups[1].Value == "}");
                        if (isBracketFound)
                        {
                            string matchStr = match.Groups[1].Value;
                            levelToIndentNext--;
                        }
                        for (int i = 0; i < levelToIndentNext; i++)
                        {
                            for (int j = 0; j < tabSize; j++)
                            {
                                codeFormatted.Append(' ');
                            }
                        }
                        if (isBracketFound)
                        {
                            codeFormatted.Append("}\r\n");
                        }

                        TextSpan editTextSpan = new TextSpan();

                        pBuffer.GetLineIndexOfPosition(start,
                                                       out editTextSpan.iStartLine,
                                                       out editTextSpan.iStartIndex);
                        pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length,
                                                       out editTextSpan.iEndLine,
                                                       out editTextSpan.iEndIndex);

                        changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString()));
                    }
                    break;
                }
                token = (ShaderToken)lexer.GetNext(ref state, out start, out end);
            }
            return(changeList);
        }
Example #12
0
 public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) {
     int hr = VSConstants.S_OK;
     int startPos = -1;
     int endPos = -1;
     if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) &&
         ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) {
         var textBuffer = vsTextLines.ToITextBuffer();
         RangeFormatter.FormatRange(TextView, textBuffer, TextRange.FromBounds(startPos, endPos), REditorSettings.FormatOptions, VsAppShell.Current);
     }
     return hr;
 }
        /// <summary>
        /// Format the content inserted by a code snippet
        /// </summary>
        public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) {
            // Example of a snippet template (taken from forprops.snippet and use ... to represent
            // indent spaces):
            //
            // for (var $property$ in $object$) {
            // ....if ($object$.hasOwnProperty($property$)) {
            // ........$selected$$end$
            // ....}
            // };
            //
            // Example of code in pBuffer (the for loop is inserted by a forprops snippet):
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ....if (object.hasOwnProperty(property)) {
            // ........
            // ....}
            // };
            //
            // Result examples:
            //
            // (1) If indent size = 2:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ..if (object.hasOwnProperty(property)) {
            // ....
            // ..}
            // };
            //
            // (2) If indent size = 2 and OpenBracesOnNewLineForControl = true:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object)
            // {
            // ..if (object.hasOwnProperty(property))
            // ..{
            // ....
            // ..}
            // };

            // Algorithm: The idea is to use Formatting.Formatter to format the inserted content.
            // However, Formatting.Formatter does not format lines that only contain spaces. For
            // example, here is how Formatting.Formatter formats the code above:
            //
            // var object = { one: 1, two: 2 };
            // for (var property in object) {
            // ..if (object.hasOwnProperty(property)) {
            // ........
            // ..}
            // };
            //
            // An additional step will be included to ensure such lines are formatted correctly.

            int baseIndentationLevel = GetViewIndentationLevelAtLine(ts[0].iStartLine);

            for (int lineNumber = ts[0].iStartLine; lineNumber <= ts[0].iEndLine; ++lineNumber) {
                string lineContent = _textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(lineNumber).GetText();

                string indentationString = GetTemplateIndentationString(lineContent);
                if (indentationString != lineContent) { // This means line contains some characters other than spaces
                    continue;
                }

                int newIndentationLevel = baseIndentationLevel + GetTemplateIndentationLevel(indentationString);

                string newIndentation = _textView.Options.IsConvertTabsToSpacesEnabled()
                    ? new string(' ', newIndentationLevel * _textView.Options.GetIndentSize())
                    : new string('\t', newIndentationLevel);

                using (var edit = _textView.TextBuffer.CreateEdit()) {
                    int indendationPos;
                    pBuffer.GetPositionOfLineIndex(lineNumber, 0, out indendationPos);
                    Span bufferIndentationSpan = new Span(indendationPos, indentationString.Length);
                    edit.Replace(bufferIndentationSpan, newIndentation);
                    edit.Apply();
                }
            }

            // Now that we have handled empty lines, use Formatter to format the inserted content.
            int startPos = 0, endPos = 0;
            pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos);
            pBuffer.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos);
            Formatting.FormattingOptions options = EditFilter.CreateFormattingOptions(_textView.Options, _textView.TextBuffer.CurrentSnapshot);
            string text = _textView.TextBuffer.CurrentSnapshot.GetText();
            EditFilter.ApplyEdits(_textView.TextBuffer, Formatting.Formatter.GetEditsForRange(text, startPos, endPos, options));

            return VSConstants.S_OK;
        }