diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs
index 26a3a01bd9..0562c0062c 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs
@@ -6,7 +6,9 @@
//
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Text;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Dom;
@@ -20,7 +22,6 @@ namespace Grunwald.BooBinding.CodeCompletion
{
public class BooParser : IParser
{
- ///IParser Interface
string[] lexerTags;
public string[] LexerTags {
@@ -80,7 +81,82 @@ namespace Grunwald.BooBinding.CodeCompletion
lineLength[i] = length;
BooCompiler compiler = new BooCompiler();
compiler.Parameters.Input.Add(new StringInput(fileName, fileContent));
- return Parse(projectContent, fileName, lineLength, compiler);
+ ICompilationUnit cu = Parse(projectContent, fileName, lineLength, compiler);
+ AddCommentsAndRegions(cu, fileContent, fileName);
+ return cu;
+ }
+
+ void AddCommentsAndRegions(ICompilationUnit cu, string fileContent, string fileName)
+ {
+ ExpressionFinder ef = new ExpressionFinder(fileName);
+ ef.ResetStateMachine();
+ int state = 0;
+ StringBuilder commentBuilder = null;
+ char commentStartChar = '\0';
+ int commentStartColumn = 0;
+
+ Stack regionTitleStack = new Stack();
+ Stack regionLineStack = new Stack();
+ Stack regionColumnStack = new Stack();
+
+ int line = 1;
+ int column = 0;
+ for (int i = 0; i < fileContent.Length; i++) {
+ column += 1;
+ char c = fileContent[i];
+ if (c == '\n') {
+ column = 0;
+ line += 1;
+ }
+ state = ef.FeedStateMachine(state, c);
+ if (state == ExpressionFinder.PossibleRegexStart) {
+ // after / could be a regular expression, do a special check for that
+ int regexEnd = ef.SkipRegularExpression(fileContent, i, fileContent.Length - 1);
+ if (regexEnd > 0) {
+ i = regexEnd;
+ } else if (regexEnd == -1) {
+ // end of file is in regex
+ return;
+ } // else: regexEnd is 0 if its not a regex
+ }
+ if (state == ExpressionFinder.LineCommentState) {
+ if (commentBuilder == null) {
+ commentStartChar = c;
+ commentStartColumn = column;
+ commentBuilder = new StringBuilder();
+ } else {
+ if (commentBuilder.Length > 0) {
+ commentBuilder.Append(c);
+ } else if (!char.IsWhiteSpace(c)) {
+ commentStartColumn = column;
+ commentBuilder.Append(c);
+ }
+ }
+ } else if (commentBuilder != null) {
+ string text = commentBuilder.ToString();
+ commentBuilder = null;
+ if (commentStartChar == '#' && text.StartsWith("region ")) {
+ regionTitleStack.Push(text.Substring(7));
+ regionLineStack.Push(line);
+ regionColumnStack.Push(commentStartColumn - 1);
+ } else if (commentStartChar == '#' && text.StartsWith("endregion") && regionTitleStack.Count > 0) {
+ // Add folding region
+ cu.FoldingRegions.Add(new FoldingRegion(regionTitleStack.Pop(),
+ new DomRegion(regionLineStack.Pop(),
+ regionColumnStack.Pop(),
+ line, column)));
+ } else {
+ foreach (string tag in lexerTags) {
+ if (text.StartsWith(tag)) {
+ Tag tagComment = new Tag(tag, new DomRegion(line, commentStartColumn));
+ tagComment.CommentString = text.Substring(tag.Length);
+ cu.TagComments.Add(tagComment);
+ break;
+ }
+ }
+ }
+ }
+ }
}
private ICompilationUnit Parse(IProjectContent projectContent, string fileName, int[] lineLength, BooCompiler compiler)
diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs
index c645521a01..3dd346bc1a 100644
--- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs
+++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs
@@ -299,6 +299,8 @@ namespace Grunwald.BooBinding.CodeCompletion
}
const int _elseIndex = 10;
+ public const int PossibleRegexStart = 12;
+ public const int LineCommentState = 13;
static readonly
int[][] _stateTable = { // " ' \ \n $ { } # / * else
@@ -327,12 +329,12 @@ namespace Grunwald.BooBinding.CodeCompletion
int commentblocks;
- void ResetStateMachine()
+ public void ResetStateMachine()
{
commentblocks = 0;
}
- int FeedStateMachine(int oldState, char c)
+ public int FeedStateMachine(int oldState, char c)
{
int charNum = (int)c;
int input;
@@ -371,7 +373,7 @@ namespace Grunwald.BooBinding.CodeCompletion
break;
char c = text[pos];
state = FeedStateMachine(state, c);
- if (state == 12) {
+ if (state == PossibleRegexStart) {
// after / could be a regular expression, do a special check for that
int regexEnd = SkipRegularExpression(text, pos, text.Length - 1);
if (regexEnd > 0) {
@@ -406,9 +408,9 @@ namespace Grunwald.BooBinding.CodeCompletion
else
inStringResult.Length = 1;
state = action;
- } else if (action == 0 || action == 12) {
+ } else if (action == 0 || action == PossibleRegexStart) {
// go to normal code
- if (action == 12) {
+ if (action == PossibleRegexStart) {
// after / could be a regular expression, do a special check for that
int regexEnd = SkipRegularExpression(inText, i, offset);
if (regexEnd > 0) {
@@ -443,7 +445,7 @@ namespace Grunwald.BooBinding.CodeCompletion
/// Skips the regular expression in inText at position pos. Returns end position of the ending / if
/// successful or 0 is no regular expression was found at the location.
/// Return -1 if maxOffset is inside the regular expression.
- int SkipRegularExpression(string inText, int pos, int maxOffset)
+ public int SkipRegularExpression(string inText, int pos, int maxOffset)
{
bool containsWhitespace;
if (pos > 0) {