From a67e3f5220cfeef8090df2352d524ca32ec902a4 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 22 Oct 2005 15:12:49 +0000 Subject: [PATCH] Fixed BOO-300: #region folding git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@609 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/CodeCompletion/BooParser.cs | 80 ++++++++++++++++++- .../Src/CodeCompletion/ExpressionFinder.cs | 14 ++-- 2 files changed, 86 insertions(+), 8 deletions(-) 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) {