internal static string Line(IVsTextLines vsTextLines, int index) { int length; vsTextLines.GetLengthOfLine(index, out length); string result; vsTextLines.GetLineText(index, 0, index, length, out result); return result; }
public List<TokenInfo> ParseLine(IVsTextLines textLines, int line, int maxTokens, out string lineOut) { int maxColumn; textLines.GetLengthOfLine(line, out maxColumn); textLines.GetLineText(line, 0, line, maxColumn, out lineOut); return Parse(lineOut, maxTokens); }
// »щет в исходном файле все блоки, обрамленные прагмой #line N / #line default private void SearchForCodeBlocks(IVsTextLines buffer) { ErrorHandler.ThrowOnFailure(buffer.LockBufferEx((uint)BufferLockFlags.BLF_READ)); try { int totalLines; ErrorHandler.ThrowOnFailure(buffer.GetLineCount(out totalLines)); var state = ParseState.WaitForBlockStart; var blockSpan = new TextSpanAndCookie(); for (int line = 0; line < totalLines; ++line) { int lineLen; ErrorHandler.ThrowOnFailure(buffer.GetLengthOfLine(line, out lineLen)); string lineText; ErrorHandler.ThrowOnFailure(buffer.GetLineText(line, 0, line, lineLen, out lineText)); if (state == ParseState.WaitForBlockStart) { var match = _linePragmaRegex.Match(lineText); if (match.Success) { blockSpan.ulHTMLCookie = uint.Parse(match.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture); blockSpan.CodeSpan = new TextSpan(); blockSpan.CodeSpan.iStartLine = line + 1; blockSpan.CodeSpan.iStartIndex = 0; state = ParseState.WaitForBlockEnd; } } else { if (lineText.Trim().StartsWith("#line default", StringComparison.InvariantCultureIgnoreCase)) { blockSpan.CodeSpan.iEndLine = line - 1; buffer.GetLengthOfLine(blockSpan.CodeSpan.iEndLine, out blockSpan.CodeSpan.iEndIndex); blocks.Add(blockSpan); blockSpan = new TextSpanAndCookie(); state = ParseState.WaitForBlockStart; } } } } finally { // Make sure that the buffer is always unlocked when we exit this function. buffer.UnlockBufferEx((uint)BufferLockFlags.BLF_READ); } }
public void InsertRange(int start, IList <string> lines) { // If the set of lines is empty we can exit now if ((null == lines) || (lines.Count == 0)) { hasMerged = true; return; } if (start < 0) { throw new ArgumentOutOfRangeException("start"); } int insertLine = start; int insertIndex = 0; // Verify that the insertion point is inside the buffer. int totalLines = LineCount; if (insertLine > totalLines) { insertLine = totalLines; } // Create the text to add to the buffer. StringBuilder builder = new StringBuilder(); if ((insertLine == totalLines) && (totalLines > 0)) { insertLine = totalLines - 1; ErrorHandler.ThrowOnFailure(textBuffer.GetLengthOfLine(insertLine, out insertIndex)); builder.AppendLine(); } foreach (string line in lines) { builder.AppendLine(line); } // Lock the buffer before changing its content. ErrorHandler.ThrowOnFailure(textBuffer.LockBuffer()); try { // Get the text to insert and pin it so that we can pass it as pointer // to the buffer's functions. string text = builder.ToString(); GCHandle handle = GCHandle.Alloc(text, GCHandleType.Pinned); try { TextSpan[] span = new TextSpan[1]; ErrorHandler.ThrowOnFailure(textBuffer.ReplaceLines(insertLine, insertIndex, insertLine, insertIndex, handle.AddrOfPinnedObject(), text.Length, span)); hasMerged = true; } finally { // Free the memory. handle.Free(); } } finally { // Make sure that the buffer is unlocked also in case of exception. textBuffer.UnlockBuffer(); } }
/// <summary> /// Validates the breakpoint location. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="line">The line.</param> /// <param name="col">The col.</param> /// <param name="pCodeSpan">The TextSpans to update.</param> /// <returns></returns> public override int ValidateBreakpointLocation(IVsTextBuffer buffer, int line, int col, TextSpan[] pCodeSpan) { // Return noimpl by default int retval = VSConstants.E_NOTIMPL; if (pCodeSpan != null) { // Make sure the span is set to at least the current // position by default. pCodeSpan[0].iStartLine = line; pCodeSpan[0].iStartIndex = 0; pCodeSpan[0].iEndLine = line; pCodeSpan[0].iEndIndex = col; } if (buffer != null) { IVsTextLines textLines = buffer as IVsTextLines; if (textLines != null) { AsmHighlighterScanner scanner = AsmHighlighterScannerFactory.GetScanner(textLines); Scanner lexer = scanner.Lexer; int maxColumn; textLines.GetLengthOfLine(line, out maxColumn); string lineToParse; textLines.GetLineText(line, 0, line, maxColumn, out lineToParse); // Setup token scanner lexer.SetSource(lineToParse, 0); int state = 0; int start, end; AsmHighlighterToken token = (AsmHighlighterToken)lexer.GetNext(ref state, out start, out end); // Set Not a valid breakpoint retval = VSConstants.S_FALSE; if ((token & AsmHighlighterToken.IS_INSTRUCTION) != 0) { if (pCodeSpan != null) { // Breakpoint covers the whole line (including comment) pCodeSpan[0].iEndIndex = maxColumn; } // Set valid breakpoint retval = VSConstants.S_OK; } } } return(retval); }
internal static string GetTextFromVsTextLines(IVsTextLines vsTextLines) { int lines; int lastLineLength; VSErrorHandler.ThrowOnFailure(vsTextLines.GetLineCount(out lines)); VSErrorHandler.ThrowOnFailure(vsTextLines.GetLengthOfLine(lines - 1, out lastLineLength)); string text; VSErrorHandler.ThrowOnFailure(vsTextLines.GetLineText(0, 0, lines - 1, lastLineLength, out text)); return(text); }
private void GetCaretPosition(out int caretLine, out int caretColumn) { ErrorHandler.ThrowOnFailure(_view.GetCaretPos(out caretLine, out caretColumn)); // Handle virtual space int lineLength; ErrorHandler.ThrowOnFailure(_lines.GetLengthOfLine(caretLine, out lineLength)); if (caretColumn > lineLength) { caretColumn = lineLength; } }
public int PositionCaretForEditing(IVsTextLines pBuffer, [ComAliasName("Microsoft.VisualStudio.TextManager.Interop.TextSpan")] VsTextSpan[] ts) { // If the formatted location of the $end$ position (the inserted comment) was on an // empty line and indented, then we have already removed the white space on that line // and the navigation location will be at column 0 on a blank line. We must now // position the caret in virtual space. pBuffer.GetLengthOfLine(ts[0].iStartLine, out var lineLength); pBuffer.GetLineText(ts[0].iStartLine, 0, ts[0].iStartLine, lineLength, out var endLineText); pBuffer.GetPositionOfLine(ts[0].iStartLine, out var endLinePosition); PositionCaretForEditingInternal(endLineText, endLinePosition); return(VSConstants.S_OK); }
public override int Read() { if (Errored || CurrentLineIndex >= LineCount) { return(-1); } if (CurrentOffset >= LineSize) { CurrentLineIndex++; if (CurrentLineIndex >= LineCount) { return(-1); } if (TextLines.GetLengthOfLine(CurrentLineIndex, out LineSize) != VSConstants.S_OK) { Errored = true; return(-1); } } if (TextLines.GetLineText(CurrentLineIndex, CurrentOffset, CurrentLineIndex, CurrentOffset, out string c) == VSConstants.S_OK) { if (c.Length != 1) { Errored = true; return(-1); } CurrentOffset++; return((int)c[0]); } else { Errored = true; return(-1); } }
public string GetText() { int totalLines; ErrorHandler.ThrowOnFailure(_textLines.GetLineCount(out totalLines)); if (totalLines > 0) { int lastLineLength; ErrorHandler.ThrowOnFailure(_textLines.GetLengthOfLine(totalLines - 1, out lastLineLength)); string text; ErrorHandler.ThrowOnFailure(_textLines.GetLineText(0, 0, totalLines - 1, lastLineLength, out text)); return(text); } return(""); }
private void MarkTests(ConfiguredProject configuredCPPProject, IVsTextLines lines) { int lineNumber; lines.GetLineCount(out lineNumber); for (int i = 0; i < lineNumber; i++) { int linelength; lines.GetLengthOfLine(i, out linelength); if (linelength <= 0) { continue; } string codeLine; lines.GetLineText(i, 0, i, linelength, out codeLine); //TODO improve this so it deals with if the class declaration isn't the first thing on the line if (!codeLine.StartsWith("TEST") && !codeLine.StartsWith("GTEST")) { continue; } //extract the test group name and test name and combine them for the gtest filter string. int endOfBrackets = codeLine.IndexOf(')'); //TODO validate the next characters after the ) are a newline, curly bracket or a comment. int startOfBrackets = codeLine.IndexOf('(') + 1; //inside of brackets string name = codeLine.Substring(startOfBrackets, endOfBrackets - startOfBrackets); name = name.Replace(',', '.').Replace(" ", ""); IVsTextLineMarker[] marker = new IVsTextLineMarker[1]; int err = lines.CreateLineMarker(TestMarkerType.ID, i, 0, i, linelength, new GTestMarker(configuredCPPProject, name), marker); if (err != VSConstants.S_OK) { throw new Exception("Could not create marker"); } _markers.Add(marker); } }
private static void addMarkersToDocument(IVsTextLines textLines) { int lineCount; textLines.GetLineCount(out lineCount); for (int i = 0; i < lineCount; ++i) { string text; int len; textLines.GetLengthOfLine(i, out len); textLines.GetLineText(i, 0, i, len, out text); string cmt = "//"; string issueKey = "PL-1357"; if (text == null || !text.Contains(cmt) || !text.Contains(issueKey)) continue; int cmtIdx = text.IndexOf(cmt); int idx = text.IndexOf(issueKey); if (idx < cmtIdx) continue; addMarker(textLines, i, idx, idx + issueKey.Length); } }
private void ExecuteUserInput() { // Get the position inside the text view. int line; int column; Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure( TextView.GetCaretPos(out line, out column)); // Get the length of the current line. int lineLength; Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure( textLines.GetLengthOfLine(line, out lineLength)); // Get the end of the read-only region. TextSpan[] span = new TextSpan[1]; Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure( textStream.ReadOnlyMarker.GetCurrentSpan(span)); // Check if there is something in this line. string text = ""; if (lineLength > span[0].iEndIndex) { // Get the text of the line. Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure( textLines.GetLineText(line, span[0].iEndIndex, line, lineLength, out text)); // Add the text to the history. history.AddEntry(text); } // Add the text to the buffer. Note that the text is always added to this buffer, // but it is added to the history only if it is not empty. if (null != inputBuffer) { inputBuffer.Add(text); } }
/// <include file='doc\Colorizer.uex' path='docs/doc[@for="Colorizer.GetLineInfo"]/*' /> public virtual TokenInfo[] GetLineInfo(IVsTextLines buffer, int line, IVsTextColorState colorState) { int length; NativeMethods.ThrowOnFailure(buffer.GetLengthOfLine(line, out length)); if (length == 0) { return(null); } string text; NativeMethods.ThrowOnFailure(buffer.GetLineText(line, 0, line, length, out text)); int state; NativeMethods.ThrowOnFailure(colorState.GetColorStateAtStartOfLine(line, out state)); if (this.cachedLine == line && this.cachedLineText == text && this.cachedLineState == state && this.cachedLineInfo != null) { return(this.cachedLineInfo); } // recolorize the line, and cache the results this.cachedLineInfo = null; this.cachedLine = line; this.cachedLineText = text; this.cachedLineState = state; // GetColorInfo will update the cache. Note that here we don't use NativeMethods.ThrowOnFailure // because the return code is the current parsing state, not an HRESULT. GetColorInfo(text, length, state); //now it should be in the cache return(this.cachedLineInfo); }
public int PositionCaretForEditing(IVsTextLines pBuffer, [ComAliasName("Microsoft.VisualStudio.TextManager.Interop.TextSpan")]VsTextSpan[] ts) { // If the formatted location of the $end$ position (the inserted comment) was on an // empty line and indented, then we have already removed the white space on that line // and the navigation location will be at column 0 on a blank line. We must now // position the caret in virtual space. int lineLength; pBuffer.GetLengthOfLine(ts[0].iStartLine, out lineLength); string endLineText; pBuffer.GetLineText(ts[0].iStartLine, 0, ts[0].iStartLine, lineLength, out endLineText); int endLinePosition; pBuffer.GetPositionOfLine(ts[0].iStartLine, out endLinePosition); PositionCaretForEditingInternal(endLineText, endLinePosition); return VSConstants.S_OK; }
public void FullScan() { Debug.WriteLine("FullScan"); m_nssource.FullScanTime = System.Environment.TickCount; m_tkm.Clear(); //m_fullscan=2; m_indent = 0; int lines_tot; int col_last; m_buffer.GetLastLineIndex(out lines_tot, out col_last); string line_text; int line_end_idx; IVsTextLines tlines = m_buffer as IVsTextLines; for (int line_loop = 0; line_loop < lines_tot; line_loop++) { tlines.GetLengthOfLine(line_loop, out line_end_idx); tlines.GetLineText(line_loop, 0, line_loop, line_end_idx, out line_text); //FullScanLine(line_text, line_loop); line_text = line_text == null ? "": line_text; m_token_type = TkType.None; m_tokenpos_start = 0; m_tokenpos_start_next = 0; //Debug.WriteLine("FullScanLine" + linenum.ToString()); while (m_token_type != TkType.EOL) { TokenNextGet2(line_text); m_tkm.Add(line_loop, m_tokenpos_start, m_tokenpos_start_next - 1, m_token_type, m_indent); } } for (uint tkloop = 0; tkloop < m_tkm.tk_tot; tkloop++) { if (m_tkm[tkloop] != null && m_tkm[tkloop].type == TkType.Other) { //uint tkspot=tkloop; for (uint tkspot = tkloop + 1; tkspot < m_tkm.tk_tot; tkspot++) { if (m_tkm[tkspot] == null) { break; } if (m_tkm[tkspot].type == TkType.ParenLeft) { m_tkm[tkloop].type = TkType.Procedure; break; } if (m_tkm[tkspot].type == TkType.Space) { continue; } if (m_tkm[tkspot].type == TkType.Star) { continue; } break; } } } }
public static void TextSpanNormalize(ref TextSpan span, IVsTextLines textLines ) { TextSpanMakePositive(ref span ); if (textLines == null) return; //adjust max. lines int lineCount; try { textLines.GetLineCount(out lineCount ); } catch (Exception) { return; } span.iEndLine = Math.Min( span.iEndLine, lineCount-1 ); //make sure the start is still before the end if (!TextSpanPositive( span)) { span.iStartLine = span.iEndLine; span.iStartIndex = span.iEndIndex; } //adjust for line length int lineLength; try { textLines.GetLengthOfLine( span.iStartLine, out lineLength ); } catch (Exception) { return; } span.iStartIndex = Math.Min( span.iStartIndex, lineLength ); try { textLines.GetLengthOfLine( span.iEndLine, out lineLength ); } catch (Exception) { return; } span.iEndIndex = Math.Min( span.iEndIndex, lineLength ); }
internal static string GetTextFromVsTextLines(IVsTextLines vsTextLines) { int lines; int lastLineLength; VSErrorHandler.ThrowOnFailure(vsTextLines.GetLineCount(out lines)); VSErrorHandler.ThrowOnFailure(vsTextLines.GetLengthOfLine(lines - 1, out lastLineLength)); string text; VSErrorHandler.ThrowOnFailure(vsTextLines.GetLineText(0, 0, lines - 1, lastLineLength, out text)); return text; }
private bool Parse() { IVsTextLines lines = _buffer; int lastLine, linelen; Marshal.ThrowExceptionForHR(lines.GetLastLineIndex(out lastLine, out linelen)); bool changed = false; int n = 0; for (int i = 0; i < lastLine; i++) { Marshal.ThrowExceptionForHR(lines.GetLengthOfLine(i, out linelen)); if (linelen < 8) { continue; // No 'Index: ' line } string start; Marshal.ThrowExceptionForHR(lines.GetLineText(i, 0, i, 7, out start)); if (!string.Equals(start, "Index: ")) { continue; } Marshal.ThrowExceptionForHR(lines.GetLineText(i, 7, i, linelen, out start)); start = start.Trim(); if (n >= _indexes.Count || _indexes[n] != start || _lines[n] != i) { changed = true; if (n <= _indexes.Count) { _lines.RemoveRange(n, _indexes.Count - n); _indexes.RemoveRange(n, _indexes.Count - n); } _indexes.Add(start); _lines.Add(i); } n++; } if (changed) { DropDownTypes.Clear(); for (int i = 0; i < _indexes.Count; i++) { TextSpan ts; ts.iStartLine = _lines[i]; ts.iStartIndex = 0; ts.iEndLine = (i + 1 < _lines.Count) ? _lines[i + 1] - 1 : lastLine; Marshal.ThrowExceptionForHR(lines.GetLengthOfLine(ts.iEndLine, out ts.iEndIndex)); ts.iEndIndex++; DropDownTypes.Add(new ComboMember(_indexes[i], 1, DROPDOWNFONTATTR.FONTATTR_PLAIN, ts)); } } return(changed); }
private void SearchForCodeBlocks(IVsTextLines buffer) { // We don't want any change in the buffer while we are parsing, // so we have to lock it. ErrorHandler.ThrowOnFailure(buffer.LockBufferEx((uint)BufferLockFlags.BLF_READ)); try { // Find the total number of lines in the buffer. int totalLines; ErrorHandler.ThrowOnFailure(buffer.GetLineCount(out totalLines)); // Set the initial values for the variables used during the parsing. SimpleParserState state = SimpleParserState.WaitForExternalSource; TextSpanAndCookie blockSpan = new TextSpanAndCookie(); // Parse all the lines in the buffer for (int line = 0; line < totalLines; ++line) { // Get the text of the current line. int lineLen; ErrorHandler.ThrowOnFailure(buffer.GetLengthOfLine(line, out lineLen)); if (0 == lineLen) { // The line is empty, no point in parsing it. continue; } string lineText; ErrorHandler.ThrowOnFailure(buffer.GetLineText(line, 0, line, lineLen, out lineText)); // Create the tokenizer. CompilerContext context = new CompilerContext("", new QuietCompilerSink()); using (SystemState systemState = new SystemState()) { tokenizer = new Tokenizer(lineText.ToCharArray(), true, systemState, context); Token token = null; string commentText; // Read all the token looking for the code blocks inside a Snippet Statements // nested in an External Source statement. Note that the standard FoxPro // parser does not return such statements and this is the reason for this // parser. while (!tokenizer.IsEndOfFile) { token = tokenizer.Next(); // This parser is strange in that it is only interested in comments: // an external code statement is in the form // #ExternalSource("PathOfTheOriginalFile", originalLineNumber) // ... (some code) ... // #End ExternalSource // and a snippet statement is // # Snippet Statement // ... (some code) ... // #End Snippet Statement // So if we want to find the text region inside a snippet nested // inside an external source, we are only interested in the comment tokens. if (TokenKind.Comment != token.Kind) { continue; } // The comments are line comments, so the comment's text is everything that // is after the beginning of the comment. commentText = CleanCommentStart(lineText.Substring(tokenizer.StartLocation.Column)); if (string.IsNullOrEmpty(commentText)) { continue; } switch (state) { case SimpleParserState.WaitForExternalSource: // This function returns a non zero value only if the comment text // is a valid external source statment. blockSpan.ulHTMLCookie = ParseExternalSource(commentText); if (0 != blockSpan.ulHTMLCookie) { // The CodeDOM provider is adding 1 to the line number, but in this // case the number is actualy the HTML editor's cookie, so we have to // restore the original value. blockSpan.ulHTMLCookie -= 1; state = SimpleParserState.WaitForSnippet; } break; case SimpleParserState.WaitForSnippet: // Check if this comment is the beginning of a snippet block. if (IsBeginSnippet(commentText)) { // This is the beginning of a snippet block, so // the actual code will start at the beginning of the // next line. blockSpan.CodeSpan.iStartLine = line + 1; // Set the default for the start index. blockSpan.CodeSpan.iStartIndex = 0; // Now we have to find the end of the snippet section // to complete the span of the code. state = SimpleParserState.WaitForEndSnippet; } else if (IsEndExternalSource(commentText)) { // This was and external block not related to the HTML editor. // Reset the text span and wait for the next external source. blockSpan = new TextSpanAndCookie(); state = SimpleParserState.WaitForExternalSource; } break; case SimpleParserState.WaitForEndSnippet: if (IsEndSnippet(commentText)) { // The code block ends at the end of the line before // this token. // Update the data about the code span and add the // block to the list of the blocks found. blockSpan.CodeSpan.iEndLine = line - 1; ErrorHandler.ThrowOnFailure( buffer.GetLengthOfLine(line - 1, out blockSpan.CodeSpan.iEndIndex)); blocks.Add(blockSpan); blockSpan = new TextSpanAndCookie(); state = SimpleParserState.WaitForEndExternal; } break; case SimpleParserState.WaitForEndExternal: // We expect only one snippet block inside the external source // section, so here we skip everything between the end of the first // snippet block and the end of the external code section. if (IsEndExternalSource(commentText)) { state = SimpleParserState.WaitForExternalSource; } break; } } } } } finally { // Make sure that the buffer is always unlocked when we exit this function. buffer.UnlockBufferEx((uint)BufferLockFlags.BLF_READ); } }
private void SearchForCodeBlocks(IVsTextLines buffer) { // We don't want any change in the buffer while we are parsing, // so we have to lock it. ErrorHandler.ThrowOnFailure(buffer.LockBufferEx((uint)BufferLockFlags.BLF_READ)); try { // Find the total number of lines in the buffer. int totalLines; ErrorHandler.ThrowOnFailure(buffer.GetLineCount(out totalLines)); // Set the initial values for the variables used during the parsing. SimpleParserState state = SimpleParserState.WaitForExternalSource; TextSpanAndCookie blockSpan = new TextSpanAndCookie(); // Parse all the lines in the buffer for (int line = 0; line < totalLines; ++line) { // Get the text of the current line. int lineLen; ErrorHandler.ThrowOnFailure(buffer.GetLengthOfLine(line, out lineLen)); if (0 == lineLen) { // The line is empty, no point in parsing it. continue; } string lineText; ErrorHandler.ThrowOnFailure(buffer.GetLineText(line, 0, line, lineLen, out lineText)); // Create the tokenizer. CompilerContext context = new CompilerContext("", new QuietCompilerSink()); using (SystemState systemState = new SystemState()) { tokenizer = new Tokenizer(lineText.ToCharArray(), true, systemState, context); Token token = null; string commentText; // Read all the token looking for the code blocks inside a Snippet Statements // nested in an External Source statement. Note that the standard IronPython // parser does not return such statements and this is the reason for this // parser. while (!tokenizer.IsEndOfFile) { token = tokenizer.Next(); // This parser is strange in that it is only interested in comments: // an external code statement is in the form // #ExternalSource("PathOfTheOriginalFile", originalLineNumber) // ... (some code) ... // #End ExternalSource // and a snippet statement is // # Snippet Statement // ... (some code) ... // #End Snippet Statement // So if we want to find the text region inside a snippet nested // inside an external source, we are only interested in the comment tokens. if (TokenKind.Comment != token.Kind) { continue; } // The comments are line comments, so the comment's text is everything that // is after the beginning of the comment. commentText = CleanCommentStart(lineText.Substring(tokenizer.StartLocation.Column)); if (string.IsNullOrEmpty(commentText)) { continue; } switch (state) { case SimpleParserState.WaitForExternalSource: // This function returns a non zero value only if the comment text // is a valid external source statment. blockSpan.ulHTMLCookie = ParseExternalSource(commentText); if (0 != blockSpan.ulHTMLCookie) { // The CodeDOM provider is adding 1 to the line number, but in this // case the number is actualy the HTML editor's cookie, so we have to // restore the original value. blockSpan.ulHTMLCookie -= 1; state = SimpleParserState.WaitForSnippet; } break; case SimpleParserState.WaitForSnippet: // Check if this comment is the beginning of a snippet block. if (IsBeginSnippet(commentText)) { // This is the beginning of a snippet block, so // the actual code will start at the beginning of the // next line. blockSpan.CodeSpan.iStartLine = line + 1; // Set the default for the start index. blockSpan.CodeSpan.iStartIndex = 0; // Now we have to find the end of the snippet section // to complete the span of the code. state = SimpleParserState.WaitForEndSnippet; } else if (IsEndExternalSource(commentText)) { // This was and external block not related to the HTML editor. // Reset the text span and wait for the next external source. blockSpan = new TextSpanAndCookie(); state = SimpleParserState.WaitForExternalSource; } break; case SimpleParserState.WaitForEndSnippet: if (IsEndSnippet(commentText)) { // The code block ends at the end of the line before // this token. // Update the data about the code span and add the // block to the list of the blocks found. blockSpan.CodeSpan.iEndLine = line - 1; ErrorHandler.ThrowOnFailure( buffer.GetLengthOfLine(line - 1, out blockSpan.CodeSpan.iEndIndex)); blocks.Add(blockSpan); blockSpan = new TextSpanAndCookie(); state = SimpleParserState.WaitForEndExternal; } break; case SimpleParserState.WaitForEndExternal: // We expect only one snippet block inside the external source // section, so here we skip everything between the end of the first // snippet block and the end of the external code section. if (IsEndExternalSource(commentText)) { state = SimpleParserState.WaitForExternalSource; } break; } } } } } finally { // Make sure that the buffer is always unlocked when we exit this function. buffer.UnlockBufferEx((uint)BufferLockFlags.BLF_READ); } }
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>(); string codeToFormat; int endOfFirstLineIndex; // Get 1st line and parse custom define pBuffer.GetLengthOfLine(0, out endOfFirstLineIndex); pBuffer.GetLineText(0, 0, 0, endOfFirstLineIndex, out codeToFormat); Dictionary<string,string> defines = ParseDefineLine(codeToFormat); AsmHighlighterScanner scanner = AsmHighlighterScannerFactory.GetScanner(filePath); Scanner lexer = scanner.Lexer; // Iterate on each line of the selection to format for (int line = span.iStartLine; line <= span.iEndLine; line++) { int lineLength; pBuffer.GetLengthOfLine(line, out lineLength); pBuffer.GetLineText(line, 0, line, lineLength, out codeToFormat); string codeToAssemble = ConvertToFasm(lexer, codeToFormat, defines); lexer.SetSource(codeToFormat, 0); int state = 0; int start, end; bool instructionFound = false, commentFound = false; int commentStart = 0; AsmHighlighterToken token = (AsmHighlighterToken)lexer.GetNext(ref state, out start, out end); while (token != AsmHighlighterToken.EOF ) { switch (token) { case AsmHighlighterToken.INSTRUCTION: case AsmHighlighterToken.FPUPROCESSOR: case AsmHighlighterToken.SIMDPROCESSOR: instructionFound = true; break; case AsmHighlighterToken.COMMENT_LINE: if (!commentFound) { commentFound = true; commentStart = start; } break; } if ( instructionFound && commentFound ) { byte[] buffer = null; try { buffer = ManagedFasm.Assemble(codeToAssemble); } catch (Exception ex) { // Unable to parse instruction... skip } if (buffer != null) { } TextSpan editTextSpan = new TextSpan(); editTextSpan.iStartLine = line; editTextSpan.iEndLine = line; editTextSpan.iStartIndex = commentStart; editTextSpan.iEndIndex = commentStart+1; if ((codeToFormat.Length - commentStart) > 2 && codeToFormat.Substring(commentStart, 2) == ";#") { editTextSpan.iEndIndex = editTextSpan.iEndIndex + 2; } string text = ";#" + ((buffer == null) ? "?" : string.Format("{0:X}",buffer.Length)); changeList.Add(new EditSpan(editTextSpan, text)); break; } token = (AsmHighlighterToken)lexer.GetNext(ref state, out start, out end); } } return changeList; }
private static void addMarkersToDocument(IVsTextLines textLines) { int lineCount; textLines.GetLineCount(out lineCount); CommentStrings commentMarkers = getCommentMarkerStrings(textLines); if (!GlobalSettings.shouldShowIssueLinks(lineCount)) { return; } bool isInBlockComment = false; for (int lineNumber = 0; lineNumber < lineCount; ++lineNumber) { string text; int lineLength; List <string> issueKeys = new List <string>(); textLines.GetLengthOfLine(lineNumber, out lineLength); textLines.GetLineText(lineNumber, 0, lineNumber, lineLength, out text); if (text == null) { continue; } if (commentMarkers.BlockOpen != null && commentMarkers.BlockClose != null) { int current = 0; MatchCollection matches; if (isInBlockComment) { matches = BlockCommentEnded.Matches(text); if (matches.Count > 0) { scanCommentedLine(textLines, lineNumber, matches[0].Value, 0, ref issueKeys); current = matches[0].Length; isInBlockComment = false; } else { scanCommentedLine(textLines, lineNumber, text, 0, ref issueKeys); maybeAddMarginMarker(textLines, lineNumber, lineLength, issueKeys); continue; } } else { if (scanForLineComment(textLines, lineNumber, text, commentMarkers, ref issueKeys)) { maybeAddMarginMarker(textLines, lineNumber, lineLength, issueKeys); continue; } } matches = BlockInOneLine.Matches(text, current); for (int i = 0; i < matches.Count; ++i) { scanCommentedLine(textLines, lineNumber, matches[i].Value, matches[i].Index, ref issueKeys); current = matches[i].Index + matches[i].Length; } if (scanForLineComment(textLines, lineNumber, text, commentMarkers, ref issueKeys)) { maybeAddMarginMarker(textLines, lineNumber, lineLength, issueKeys); continue; } matches = BlockCommentStarted.Matches(text, current); if (matches.Count > 0) { isInBlockComment = true; scanCommentedLine(textLines, lineNumber, matches[0].Value, matches[0].Index, ref issueKeys); } } else { if (commentMarkers.Line == null) { maybeAddMarginMarker(textLines, lineNumber, lineLength, issueKeys); continue; } scanForLineComment(textLines, lineNumber, text, commentMarkers, ref issueKeys); } maybeAddMarginMarker(textLines, lineNumber, lineLength, issueKeys); } }
/// <summary> /// Get entire TextLines buffer as a TextSpan /// </summary> /// <param name="pBuffer"></param> /// <returns></returns> private static TextSpan GetBufferSpan(IVsTextLines textBuffer) { ArgumentValidation.CheckForNullReference(textBuffer, "textBuffer"); var lineCount = 0; var charCount = 0; // Get line count for the whole buffer. var result = textBuffer.GetLineCount(out lineCount); if (result == VSConstants.S_OK && lineCount > 0) { // Get char count for last line. result = textBuffer.GetLengthOfLine(lineCount - 1, out charCount); if (result != VSConstants.S_OK) { charCount = 0; } } else { lineCount = 0; } // Create a TextSpan from begin to end of the text buffer. var span = new TextSpan(); span.iStartLine = 0; span.iStartIndex = 0; span.iEndLine = lineCount - 1 > 0 ? lineCount - 1 : 0; span.iEndIndex = charCount > 0 ? charCount : 0; return span; }
public static void QueueMessage( string subCategory, string errorCode, string file, string msg, int line, int column, int endLine, int endColumn, IVsHierarchy hierarchy, bool isError = true, string helpKeyword = "", string senderName = "", bool refresh = true) { if (Contains(subCategory, errorCode, file, msg, line, column, hierarchy, isError, helpKeyword, senderName)) { return; } // This enqueues a function that will later be run on the main (UI) thread TextSpan span; string filePath; MARKERTYPE marker; TaskErrorCategory category; VisualRust.Project.RustProjectNode rustProject = hierarchy as VisualRust.Project.RustProjectNode; var ivsSolution = (IVsSolution)Package.GetGlobalService(typeof(IVsSolution)); var dte = (EnvDTE80.DTE2)Package.GetGlobalService(typeof(EnvDTE.DTE)); span = new TextSpan(); // spans require zero-based indices span.iStartLine = line - 1; span.iEndLine = endLine - 1; span.iStartIndex = column - 1; span.iEndIndex = endColumn - 1; filePath = Path.Combine(Path.GetDirectoryName(rustProject.GetCanonicalName()), file); if (isError) { marker = MARKERTYPE.MARKER_CODESENSE_ERROR; // red squiggles category = TaskErrorCategory.Error; } else { marker = MARKERTYPE.MARKER_COMPILE_ERROR; // red squiggles category = TaskErrorCategory.Warning; } if (span.iEndLine == -1) { span.iEndLine = span.iStartLine; } if (span.iEndIndex == -1) { span.iEndIndex = span.iStartIndex; } IVsUIShellOpenDocument openDoc = serviceProvider.GetService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; if (openDoc == null) { throw new NotImplementedException(); // TODO } IVsWindowFrame frame; IOleServiceProvider sp; IVsUIHierarchy hier; uint itemid; Guid logicalView = Microsoft.VisualStudio.VSConstants.LOGVIEWID_Code; IVsTextLines buffer = null; // Notes about acquiring the buffer: // If the file physically exists then this will open the document in the current project. It doesn't matter if the file is a member of the project. // Also, it doesn't matter if this is a Rust file. For example, an error in Microsoft.Common.targets will cause a file to be opened here. // However, opening the document does not mean it will be shown in VS. if (!Microsoft.VisualStudio.ErrorHandler.Failed(openDoc.OpenDocumentViaProject(file, ref logicalView, out sp, out hier, out itemid, out frame)) && frame != null) { object docData; frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out docData); // Get the text lines buffer = docData as IVsTextLines; if (buffer == null) { IVsTextBufferProvider bufferProvider = docData as IVsTextBufferProvider; if (bufferProvider != null) { bufferProvider.GetTextBuffer(out buffer); } } } if (span.iEndLine > span.iStartLine) { span.iEndLine = span.iStartLine; int lineLength = 0; if (buffer.GetLengthOfLine(span.iStartLine, out lineLength) == Microsoft.VisualStudio.VSConstants.S_OK) { span.iEndIndex = lineLength - 1; } } DocumentTask task = new DocumentTask(serviceProvider, buffer, marker, span, file); task.ErrorCategory = category; task.Document = file; task.Line = span.iStartLine; task.Column = span.iStartIndex; task.Priority = category == TaskErrorCategory.Error ? TaskPriority.High : TaskPriority.Normal; task.Text = msg; task.Category = TaskCategory.BuildCompile; task.HierarchyItem = hierarchy; Add(task); if (refresh) { Refresh(); } // NOTE: Unlike output we dont want to interactively report the tasks. So we never queue // call ReportQueuedTasks here. We do this when the build finishes. }
// Считывает содержимое файла из буфера, связанного с документом. // Такой способ позволяет получить еще не сохраненный на диск контент. private string ReadSourceFromBuffer() { IVsRunningDocumentTable rdt = NemerlePackage.GetGlobalService(typeof(IVsRunningDocumentTable)) as IVsRunningDocumentTable; if (rdt != null) { IEnumRunningDocuments documents; rdt.GetRunningDocumentsEnum(out documents); IntPtr documentData = IntPtr.Zero; uint[] docCookie = new uint[1]; uint fetched; while ((Microsoft.VisualStudio.VSConstants.S_OK == documents.Next(1, docCookie, out fetched)) && (1 == fetched)) { uint flags; uint editLocks; uint readLocks; string moniker; IVsHierarchy docHierarchy; uint docId; IntPtr docData = IntPtr.Zero; try { ErrorHandler.ThrowOnFailure(rdt.GetDocumentInfo(docCookie[0], out flags, out readLocks, out editLocks, out moniker, out docHierarchy, out docId, out docData)); // Check if this document is the one we are looking for. if (docId == _id && _hierarchy.Equals(docHierarchy)) { documentData = docData; docData = IntPtr.Zero; break; } } finally { if (docData != IntPtr.Zero) { Marshal.Release(docData); } } } if (documentData != IntPtr.Zero) { object obj = Marshal.GetObjectForIUnknown(documentData); IVsTextLines txtLines = obj as IVsTextLines; int totalLines; ErrorHandler.ThrowOnFailure(txtLines.GetLineCount(out totalLines)); StringBuilder sb = new StringBuilder(); for (int line = 0; line < totalLines; ++line) { int lineLen; ErrorHandler.ThrowOnFailure(txtLines.GetLengthOfLine(line, out lineLen)); string lineText; ErrorHandler.ThrowOnFailure(txtLines.GetLineText(line, 0, line, lineLen, out lineText)); sb.AppendLine(lineText); } return(sb.ToString()); } } return(null); }
public int GetLengthOfLine(int iLine, out int piLength) { return(_textBuffer.GetLengthOfLine(iLine, out piLength)); }
public int PositionCaretForEditing(IVsTextLines pBuffer, [ComAliasName("Microsoft.VisualStudio.TextManager.Interop.TextSpan")]VsTextSpan[] ts) { // If the formatted location of the $end$ position (the inserted comment) was on an // empty line and indented, then we have already removed the white space on that line // and the navigation location will be at column 0 on a blank line. We must now // position the caret in virtual space. if (indentCaretOnCommit) { int lineLength; pBuffer.GetLengthOfLine(ts[0].iStartLine, out lineLength); string lineText; pBuffer.GetLineText(ts[0].iStartLine, 0, ts[0].iStartLine, lineLength, out lineText); if (lineText == string.Empty) { int endLinePosition; pBuffer.GetPositionOfLine(ts[0].iStartLine, out endLinePosition); TextView.TryMoveCaretToAndEnsureVisible(new VirtualSnapshotPoint(TextView.TextSnapshot.GetPoint(endLinePosition), indentDepth)); } } return VSConstants.S_OK; }
/// <summary> /// Generic test for the ad-hoc inline commands. /// </summary> /// <typeparam name="T">Expected type of result items</typeparam> /// <param name="target">Command to execute</param> /// <param name="view"></param> /// <param name="lines"></param> /// <param name="expectedList">List of expected result items</param> protected void RunTest <T>(InlineCommand_Accessor <T> target, IVsTextView view, IVsTextLines lines, List <AbstractResultItem> expectedList) where T : AbstractResultItem, new() { Random rnd = new Random(); target.InitializeVariables(); // simulate right-click around each of expected result items and verify that move command reacts foreach (AbstractResultItem expectedItem in expectedList) { Assert.IsTrue(expectedItem.ReplaceSpan.iStartLine >= 0); Assert.IsTrue(expectedItem.ReplaceSpan.iEndLine >= 0); // each result item will be clicked at every its characted for (int line = expectedItem.ReplaceSpan.iStartLine; line <= expectedItem.ReplaceSpan.iEndLine; line++) { int begin; int end; if (line == expectedItem.ReplaceSpan.iStartLine) { begin = expectedItem.ReplaceSpan.iStartIndex; } else { begin = 0; } if (line == expectedItem.ReplaceSpan.iEndLine) { end = expectedItem.ReplaceSpan.iEndIndex; } else { lines.GetLengthOfLine(line, out end); } for (int column = begin; column <= end; column++) { // perform right-click view.SetSelection(line, column, line, column); // run the command var actualItem = target.GetCodeReferenceResultItem(); Assert.IsNotNull(actualItem, "Actual item cannot be null"); actualItem.IsWithinLocalizableFalse = expectedItem.IsWithinLocalizableFalse; // can be ignored BatchTestsBase.ValidateItems(expectedItem, actualItem); } // create random selections within the result item for (int i = 0; i < 5; i++) { int b = rnd.Next(begin, end + 1); int e = rnd.Next(b, end + 1); view.SetSelection(line, b, line, e); var actualItem = target.GetCodeReferenceResultItem(); actualItem.IsWithinLocalizableFalse = expectedItem.IsWithinLocalizableFalse; // can be ignored BatchTestsBase.ValidateItems(expectedItem, actualItem); } } if (expectedItem.ReplaceSpan.iStartIndex - 1 >= 0) { view.SetSelection(expectedItem.ReplaceSpan.iStartLine, expectedItem.ReplaceSpan.iStartIndex - 1, expectedItem.ReplaceSpan.iStartLine, expectedItem.ReplaceSpan.iStartIndex - 1); Assert.IsNull(target.GetCodeReferenceResultItem(), "For item " + expectedItem.Value); } int lineLength; lines.GetLengthOfLine(expectedItem.ReplaceSpan.iEndLine, out lineLength); if (expectedItem.ReplaceSpan.iEndIndex + 1 <= lineLength) { view.SetSelection(expectedItem.ReplaceSpan.iEndLine, expectedItem.ReplaceSpan.iEndIndex + 1, expectedItem.ReplaceSpan.iEndLine, expectedItem.ReplaceSpan.iEndIndex + 1); Assert.IsNull(target.GetCodeReferenceResultItem(), "For item " + expectedItem.Value); } } }
/// <devdoc>Pins the text span to valid line bounds returned from IVsTextLines.</devdoc> internal static void Normalize(ref TextSpan span, IVsTextLines textLines) { MakePositive(ref span); if (textLines == null) return; //adjust max. lines int lineCount; if (NativeMethods.Failed(textLines.GetLineCount(out lineCount))) return; span.iEndLine = Math.Min(span.iEndLine, lineCount - 1); //make sure the start is still before the end if (!IsPositive(span)) { span.iStartLine = span.iEndLine; span.iStartIndex = span.iEndIndex; } //adjust for line length int lineLength; if (NativeMethods.Failed(textLines.GetLengthOfLine(span.iStartLine, out lineLength))) return; span.iStartIndex = Math.Min(span.iStartIndex, lineLength); if (NativeMethods.Failed(textLines.GetLengthOfLine(span.iEndLine, out lineLength))) return; span.iEndIndex = Math.Min(span.iEndIndex, lineLength); }
/// <include file='doc\Colorizer.uex' path='docs/doc[@for="Colorizer.GetLineInfo"]/*' /> public virtual TokenInfo[] GetLineInfo(IVsTextLines buffer, int line, IVsTextColorState colorState) { int length; NativeMethods.ThrowOnFailure(buffer.GetLengthOfLine(line, out length)); if (length == 0) return null; string text; NativeMethods.ThrowOnFailure(buffer.GetLineText(line, 0, line, length, out text)); int state; NativeMethods.ThrowOnFailure(colorState.GetColorStateAtStartOfLine(line, out state)); if (this.cachedLine == line && this.cachedLineText == text && this.cachedLineState == state && this.cachedLineInfo != null) { return this.cachedLineInfo; } // recolorize the line, and cache the results this.cachedLineInfo = null; this.cachedLine = line; this.cachedLineText = text; this.cachedLineState = state; NativeMethods.ThrowOnFailure(GetColorInfo(text, length, state)); //now it should be in the cache return this.cachedLineInfo; }
/// <include file='doc\Colorizer.uex' path='docs/doc[@for="Colorizer.GetLineInfo"]/*' /> public virtual TokenInfo[] GetLineInfo(IVsTextLines buffer, int line, IVsTextColorState colorState) { int length; NativeMethods.ThrowOnFailure(buffer.GetLengthOfLine(line, out length)); if (length == 0) return null; string text; NativeMethods.ThrowOnFailure(buffer.GetLineText(line, 0, line, length, out text)); int state; NativeMethods.ThrowOnFailure(colorState.GetColorStateAtStartOfLine(line, out state)); if (this.cachedLine == line && this.cachedLineText == text && this.cachedLineState == state && this.cachedLineInfo != null) { return this.cachedLineInfo; } // recolorize the line, and cache the results this.cachedLineInfo = null; this.cachedLine = line; this.cachedLineText = text; this.cachedLineState = state; // GetColorInfo will update the cache. Note that here we don't use NativeMethods.ThrowOnFailure // because the return code is the current parsing state, not an HRESULT. GetColorInfo(text, length, state); //now it should be in the cache return this.cachedLineInfo; }
/// <summary> /// Generic test for the "(selection)" commands /// </summary> /// <param name="target">Command to process</param> /// <param name="file">File path</param> /// <param name="view"></param> /// <param name="lines"></param> /// <param name="getExpected">Function that returns list of expected results for specified file path</param> protected void GenericSelectionTest(AbstractBatchCommand_Accessor target, string file, IVsTextView view, IVsTextLines lines, Func <string, List <AbstractResultItem> > getExpected) { Agent.EnsureSolutionOpen(); int lineCount; lines.GetLineCount(out lineCount); Random rnd = new Random(); for (int i = 0; i < 20; i++) { // initialize selection range int beginLine = rnd.Next(lineCount); int endLine = beginLine + rnd.Next(Math.Min(lineCount, beginLine + i) - beginLine); int beginLineLength, endLineLength; lines.GetLengthOfLine(beginLine, out beginLineLength); lines.GetLengthOfLine(endLine, out endLineLength); int beginColumn = rnd.Next(beginLineLength); int endColumn = beginLine == endLine ? beginColumn + (rnd.Next(Math.Min(endLineLength, beginColumn + i) - beginColumn)) : rnd.Next(endLineLength); if (beginLine == endLine && beginColumn == endColumn) { endColumn++; } // set the selection view.SetSelection(beginLine, beginColumn, endLine, endColumn); target.InitializeSelection(); // obtain the list of expected results List <AbstractResultItem> expectedList = new List <AbstractResultItem>(); foreach (AbstractResultItem expected in getExpected(file)) { if (!target.IsItemOutsideSelection(expected)) { expectedList.Add(expected); } } // run the command target.ProcessSelection(true); // compare the results if (target is BatchMoveCommand_Accessor) { ValidateResults(expectedList, (target as BatchMoveCommand_Accessor).Results); } else if (target is BatchInlineCommand_Accessor) { ValidateResults(expectedList, (target as BatchInlineCommand_Accessor).Results); } else { Assert.Fail("Unkown parent command type"); } Assert.IsTrue(expectedList.Count == 0 || VLDocumentViewsManager.IsFileLocked(file)); VLDocumentViewsManager.ReleaseLocks(); Assert.IsFalse(VLDocumentViewsManager.IsFileLocked(file)); } // close the window Window win = VsShellUtilities.GetWindowObject(VLDocumentViewsManager.GetWindowFrameForFile(file, false)); win.Detach(); win.Close(vsSaveChanges.vsSaveChangesNo); }
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>(); string codeToFormat; int endOfFirstLineIndex; // Get 1st line and parse custom define pBuffer.GetLengthOfLine(0, out endOfFirstLineIndex); pBuffer.GetLineText(0, 0, 0, endOfFirstLineIndex, out codeToFormat); Dictionary <string, string> defines = ParseDefineLine(codeToFormat); AsmHighlighterScanner scanner = AsmHighlighterScannerFactory.GetScanner(filePath); Scanner lexer = scanner.Lexer; // Iterate on each line of the selection to format for (int line = span.iStartLine; line <= span.iEndLine; line++) { int lineLength; pBuffer.GetLengthOfLine(line, out lineLength); pBuffer.GetLineText(line, 0, line, lineLength, out codeToFormat); string codeToAssemble = ConvertToFasm(lexer, codeToFormat, defines); lexer.SetSource(codeToFormat, 0); int state = 0; int start, end; bool instructionFound = false, commentFound = false; int commentStart = 0; AsmHighlighterToken token = (AsmHighlighterToken)lexer.GetNext(ref state, out start, out end); while (token != AsmHighlighterToken.EOF) { switch (token) { case AsmHighlighterToken.INSTRUCTION: case AsmHighlighterToken.FPUPROCESSOR: case AsmHighlighterToken.SIMDPROCESSOR: instructionFound = true; break; case AsmHighlighterToken.COMMENT_LINE: if (!commentFound) { commentFound = true; commentStart = start; } break; } if (instructionFound && commentFound) { byte[] buffer = null; try { buffer = ManagedFasm.Assemble(codeToAssemble); } catch (Exception ex) { // Unable to parse instruction... skip } if (buffer != null) { } TextSpan editTextSpan = new TextSpan(); editTextSpan.iStartLine = line; editTextSpan.iEndLine = line; editTextSpan.iStartIndex = commentStart; editTextSpan.iEndIndex = commentStart + 1; if ((codeToFormat.Length - commentStart) > 2 && codeToFormat.Substring(commentStart, 2) == ";#") { editTextSpan.iEndIndex = editTextSpan.iEndIndex + 2; } string text = ";#" + ((buffer == null) ? "?" : string.Format("{0:X}", buffer.Length)); changeList.Add(new EditSpan(editTextSpan, text)); break; } token = (AsmHighlighterToken)lexer.GetNext(ref state, out start, out end); } } return(changeList); }
public int CollapseToDefinitions(IVsTextLines textLines, IVsOutliningSession session){ if (textLines == null || session == null) return (int)HResult.E_INVALIDARG; int lastLine; int lastIdx; string text; textLines.GetLineCount(out lastLine ); textLines.GetLengthOfLine(--lastLine, out lastIdx); textLines.GetLineText(0, 0, lastLine, lastIdx, out text); NewOutlineRegion[] outlineRegions = this.GetCollapsibleRegions(text, VsShell.GetFilePath(textLines)); if (outlineRegions != null && outlineRegions.Length > 0) session.AddOutlineRegions((uint)ADD_OUTLINE_REGION_FLAGS.AOR_PRESERVE_EXISTING, outlineRegions.Length, outlineRegions); return 0; }
public bool GotoNextToken(DelphiToken aToken, out int aStartLine, out int aStartIndex, out int aEndLine, out int aEndIndex) { int lCurrLine, lCurrIndex, lLineLen, lState = 0; int lLastState = 0; string lLineText = ""; TokenInfo lTokenInfo = new TokenInfo(); lCurrLine = StartLine; lCurrIndex = StartIndex; int lAddChrs = StartIndex; aStartIndex = 0; aStartLine = 0; aEndIndex = 0; aEndLine = 0; lLineLen = 0; if (aToken == DelphiToken.None) { return(false); } System.Diagnostics.Debug.Assert(aToken != EndToken, "End Token and aToken parameter match in GotoNextToken"); bool result = false; while (lCurrLine <= EndLine) { if (lCurrLine == EndLine - 2) { result = false; } if (lLineText == "") { // TODO: Read and check out whats the diff between NativeMethods.ThrowOnFailure and ErrorHandler.ThrowOnFailure? ErrorHandler.ThrowOnFailure(FTextLines.GetLengthOfLine(lCurrLine, out lLineLen)); ErrorHandler.ThrowOnFailure(FTextLines.GetLineText(lCurrLine, 0, lCurrLine, lLineLen, out lLineText)); FScanner.SetSource(lLineText, lCurrIndex); } lTokenInfo.Type = TokenType.Unknown; lTokenInfo.EndIndex = lLineLen - 1; try { FScanner.ScanTokenAndProvideInfoAboutIt(lTokenInfo, ref lState); } catch { /* Do we care? */ } // lTokenInfo.StartIndex will = 0 for the first token even if // in line "FScanner.SetSource(lLineText, lCurrIndex)" lCurrIndex > 0 // so we will need to add some values to make the values correct. if (lAddChrs > 0) { lTokenInfo.EndIndex += lAddChrs; lTokenInfo.StartIndex += lAddChrs; } // if we have reached your end token then exit if (lTokenInfo.Token == (int)EndToken && lState == DelphiScanner.YYINITIAL) { break; } aEndIndex = lTokenInfo.EndIndex; // set end point aEndLine = lCurrLine; // set end line lCurrIndex = lTokenInfo.StartIndex; // Set new point if ((lState == DelphiScanner.YYINITIAL) && (lTokenInfo.Token == (int)aToken) && (lState != lLastState)) { // no worries we found have the StartIndex and StartLine already result = true; } else if ((lState == DelphiScanner.YYINITIAL) || (lState != lLastState)) { aStartLine = lCurrLine; aStartIndex = lCurrIndex; lLastState = lState; result = (lTokenInfo.Token == (int)aToken); } if (result) { break; } lCurrIndex = lTokenInfo.EndIndex + 1; if (lCurrIndex >= lLineLen) { lLineText = ""; lCurrIndex = 0; lAddChrs = 0; lCurrLine++; } } if (result) { StartIndex = lTokenInfo.EndIndex + 1; StartLine = aEndLine; // aEndIndex is correct but the GetLineText method does not read the text out correctly. ErrorHandler.ThrowOnFailure(FTextLines.GetLineText(aStartLine, aStartIndex, aEndLine, aEndIndex + 1, out FTokenValue)); } return(result); }
/// <summary> /// @see also: https://github.com/Trass3r/AsmHighlighter/blob/master/AsmHighlighter/AsmHighlighterFormatHelper.cs /// @see also: https://github.com/samizzo/nshader/blob/master/NShaderVS/NShaderFormatHelper.cs /// https://msdn.microsoft.com/en-us/library/bb164633.aspx /// </summary> /// <param name="pBuffer"></param> /// <param name="span"></param> /// <param name="tabSize"></param> /// <returns></returns> internal static List <EditSpan> ReformatCode(IVsTextLines pBuffer, int[] indents, bool[] comments, bool[] unFormat, TextSpan span) { Scanner lex = new Scanner(); List <EditSpan> changeList = new List <EditSpan>(); string line = ""; for (int i = span.iStartLine; i <= span.iEndLine; ++i) { if (unFormat[i] || comments[i]) { continue; } bool binaryOp = false; int startIndex = 0; int endIndex = 0; pBuffer.GetLengthOfLine(i, out endIndex); pBuffer.GetLineText(i, startIndex, i, endIndex, out line); //rules of formatting //rule 1: insert space before and after binary operator if there not any //rule 2: insert space after comma, semicolon if there not any //rule 3: indentation increase inside block //rule 4: multiple spaces replaced by a single space //rule 5: no spaces after left parentheses("(") and before right parentheses(")") //rule 6: no spaces between identifier and left parentheses("(") //rule 7: no spaces before and after colon ":" int state = 0, start = 0, end = 0; int firstSpaceEnd = -1; lex.SetSource(line, 0); int token = lex.GetNext(ref state, out start, out end); if ((Tokens)token == Tokens.LEX_WHITE) // skip spaces at front of the line { firstSpaceEnd = end; token = lex.GetNext(ref state, out start, out end); } // set indentation if (!(firstSpaceEnd == -1 && indents[i] == 0)) { string indentation = ""; for (int j = 0; j < indents[i]; ++j) { indentation = "\t" + indentation; } TextSpan firstSpaceSpan = new TextSpan(); firstSpaceSpan.iStartLine = i; firstSpaceSpan.iEndLine = i; firstSpaceSpan.iStartIndex = 0; firstSpaceSpan.iEndIndex = firstSpaceEnd + 1; changeList.Add(new EditSpan(firstSpaceSpan, indentation)); } FormatToken currentToken = new FormatToken((int)token, start, end); FormatToken lastToken = new FormatToken((int)Tokens.EOF, start - 1, start - 1); while (currentToken.token != (int)Tokens.EOF) { token = lex.GetNext(ref state, out start, out end); // fix issue of last unknow space if (start > end) { break; } FormatToken nextToken = new FormatToken((int)token, start, end); if (currentToken.token == (int)Tokens.LEX_WHITE && nextToken.token != (int)Tokens.LEX_COMMENT) // spaces, leave the space before comment { string SpaceorEmpty = " "; if (nextToken.token == (int)Tokens.RPAREN || // if meet right paren, remove spaces (nextToken.token == (int)Tokens.LPAREN && // rule 6 lastToken.token != (int)Tokens.KWFUNCTION) || nextToken.token == (int)Tokens.LBRACKET || nextToken.token == (int)Tokens.COLON || lastToken.token == (int)Tokens.COLON) { SpaceorEmpty = ""; } TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.startIndex; spaceEdit.iEndIndex = currentToken.endIndex + 1; changeList.Add(new EditSpan(spaceEdit, SpaceorEmpty)); } else if (currentToken.token == (int)Tokens.COMMA || currentToken.token == (int)Tokens.SEMICOLON) // comma, semicolon { if (nextToken.token != (int)Tokens.LEX_WHITE && nextToken.token != (int)Tokens.EOF) { string space = " "; TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.endIndex + 1; spaceEdit.iEndIndex = currentToken.endIndex + 1; changeList.Add(new EditSpan(spaceEdit, space)); } } else if (currentToken.token == (int)Tokens.PLUS || //binary operators currentToken.token == (int)Tokens.ASTERISK || currentToken.token == (int)Tokens.SLASH || currentToken.token == (int)Tokens.EQUAL) { if (lastToken.token != (int)Tokens.LEX_WHITE && lastToken.token != (int)Tokens.EOF) { string space = " "; TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.startIndex; spaceEdit.iEndIndex = currentToken.startIndex; changeList.Add(new EditSpan(spaceEdit, space)); } if (nextToken.token != (int)Tokens.LEX_WHITE && nextToken.token != (int)Tokens.EOF) { string space = " "; TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.endIndex + 1; spaceEdit.iEndIndex = currentToken.endIndex + 1; changeList.Add(new EditSpan(spaceEdit, space)); } } else if ((currentToken.token == (int)Tokens.MINUS) && //binary operators binaryOp) { if (lastToken.token != (int)Tokens.LEX_WHITE && lastToken.token != (int)Tokens.EOF) { string space = " "; TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.startIndex; spaceEdit.iEndIndex = currentToken.startIndex; changeList.Add(new EditSpan(spaceEdit, space)); } if (nextToken.token != (int)Tokens.LEX_WHITE && nextToken.token != (int)Tokens.EOF) { string space = " "; TextSpan spaceEdit = new TextSpan(); spaceEdit.iStartLine = i; spaceEdit.iEndLine = i; spaceEdit.iStartIndex = currentToken.endIndex + 1; spaceEdit.iEndIndex = currentToken.endIndex + 1; changeList.Add(new EditSpan(spaceEdit, space)); } binaryOp = false; } else if (currentToken.token == (int)Tokens.NUMBER) { if (nextToken.token == (int)Tokens.LEX_WHITE) { // get new nextToken token = lex.GetNext(ref state, out start, out end); if (start > end) { break; } if (token == (int)Tokens.PLUS || token == (int)Tokens.MINUS) { binaryOp = true; } //nextToken = new FormatToken(token, start, end); } else if (nextToken.token == (int)Tokens.PLUS || nextToken.token == (int)Tokens.MINUS) { binaryOp = true; } } else if (currentToken.token == (int)Tokens.LPAREN && nextToken.token == (int)Tokens.LEX_WHITE) { string empty = ""; TextSpan emptyEdit = new TextSpan(); emptyEdit.iStartLine = i; emptyEdit.iEndLine = i; emptyEdit.iStartIndex = nextToken.startIndex; emptyEdit.iEndIndex = nextToken.endIndex + 1; changeList.Add(new EditSpan(emptyEdit, empty)); // get new nextToken token = lex.GetNext(ref state, out start, out end); // fix issue of last unknow space if (start > end) { break; } nextToken = new FormatToken(token, start, end); } lastToken = currentToken; currentToken = nextToken; } } return(changeList); }