Browse Source

Fixed BOO-300: #region folding

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@609 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
a67e3f5220
  1. 80
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs
  2. 14
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs

80
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs

@ -6,7 +6,9 @@
// </file> // </file>
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Dom;
@ -20,7 +22,6 @@ namespace Grunwald.BooBinding.CodeCompletion
{ {
public class BooParser : IParser public class BooParser : IParser
{ {
///<summary>IParser Interface</summary>
string[] lexerTags; string[] lexerTags;
public string[] LexerTags { public string[] LexerTags {
@ -80,7 +81,82 @@ namespace Grunwald.BooBinding.CodeCompletion
lineLength[i] = length; lineLength[i] = length;
BooCompiler compiler = new BooCompiler(); BooCompiler compiler = new BooCompiler();
compiler.Parameters.Input.Add(new StringInput(fileName, fileContent)); 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<string> regionTitleStack = new Stack<string>();
Stack<int> regionLineStack = new Stack<int>();
Stack<int> regionColumnStack = new Stack<int>();
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) private ICompilationUnit Parse(IProjectContent projectContent, string fileName, int[] lineLength, BooCompiler compiler)

14
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs

@ -299,6 +299,8 @@ namespace Grunwald.BooBinding.CodeCompletion
} }
const int _elseIndex = 10; const int _elseIndex = 10;
public const int PossibleRegexStart = 12;
public const int LineCommentState = 13;
static readonly static readonly
int[][] _stateTable = { // " ' \ \n $ { } # / * else int[][] _stateTable = { // " ' \ \n $ { } # / * else
@ -327,12 +329,12 @@ namespace Grunwald.BooBinding.CodeCompletion
int commentblocks; int commentblocks;
void ResetStateMachine() public void ResetStateMachine()
{ {
commentblocks = 0; commentblocks = 0;
} }
int FeedStateMachine(int oldState, char c) public int FeedStateMachine(int oldState, char c)
{ {
int charNum = (int)c; int charNum = (int)c;
int input; int input;
@ -371,7 +373,7 @@ namespace Grunwald.BooBinding.CodeCompletion
break; break;
char c = text[pos]; char c = text[pos];
state = FeedStateMachine(state, c); state = FeedStateMachine(state, c);
if (state == 12) { if (state == PossibleRegexStart) {
// after / could be a regular expression, do a special check for that // after / could be a regular expression, do a special check for that
int regexEnd = SkipRegularExpression(text, pos, text.Length - 1); int regexEnd = SkipRegularExpression(text, pos, text.Length - 1);
if (regexEnd > 0) { if (regexEnd > 0) {
@ -406,9 +408,9 @@ namespace Grunwald.BooBinding.CodeCompletion
else else
inStringResult.Length = 1; inStringResult.Length = 1;
state = action; state = action;
} else if (action == 0 || action == 12) { } else if (action == 0 || action == PossibleRegexStart) {
// go to normal code // go to normal code
if (action == 12) { if (action == PossibleRegexStart) {
// after / could be a regular expression, do a special check for that // after / could be a regular expression, do a special check for that
int regexEnd = SkipRegularExpression(inText, i, offset); int regexEnd = SkipRegularExpression(inText, i, offset);
if (regexEnd > 0) { if (regexEnd > 0) {
@ -443,7 +445,7 @@ namespace Grunwald.BooBinding.CodeCompletion
/// <summary>Skips the regular expression in inText at position pos. Returns end position of the ending / if /// <summary>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. /// successful or 0 is no regular expression was found at the location.
/// Return -1 if maxOffset is inside the regular expression.</summary> /// Return -1 if maxOffset is inside the regular expression.</summary>
int SkipRegularExpression(string inText, int pos, int maxOffset) public int SkipRegularExpression(string inText, int pos, int maxOffset)
{ {
bool containsWhitespace; bool containsWhitespace;
if (pos > 0) { if (pos > 0) {

Loading…
Cancel
Save