// »щет в исходном файле все блоки, обрамленные прагмой #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); } }
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); } }
public int LockBufferEx(uint dwFlags) { return(_textBuffer.LockBufferEx(dwFlags)); }
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); } }