[svn] r7562: vs-plugin/trunk: Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n Nemerle.VsI...

VladD2 svnadmin at nemerle.org
Sat Mar 31 08:01:53 CEST 2007


Log:
Finish match braces.

Author: VladD2
Date: Sat Mar 31 08:01:50 2007
New Revision: 7562

Modified:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n	Sat Mar 31 08:01:50 2007
@@ -20,6 +20,11 @@
       Keywords = manager.CoreEnv.Keywords;
     }
 
+    public SetFileName(fileName : string) : void
+    {
+      file_idx = Location.GetFileIndex(IO.Path.GetFullPath(fileName));
+    }
+
     public SetLine(
       lineNumber  : int,
       line        : string,
@@ -901,5 +906,5 @@
       when (obj != null)
         _ = obj.ToString();
     }
-  }
+  } // ScanLexer class
 }

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs	Sat Mar 31 08:01:50 2007
@@ -60,6 +60,8 @@
 
 		#region ParseSource
 
+		#region ParseSource()
+
 		public override AuthoringScope ParseSource(ParseRequest request)
 		{
 			if (request == null)
@@ -82,14 +84,12 @@
 				case ParseReason.Autos:
 				case ParseReason.CodeSpan:
 				case ParseReason.DisplayMemberList:
-				case ParseReason.HighlightBraces:
 				case ParseReason.None:
 				case ParseReason.MemberSelectAndHighlightBraces: 
 					Trace.WriteLine("Request reason '" + request.Reason + "' not handled.");
 					break;
-				case ParseReason.MatchBraces:
-					MatchBraces(request);
-					break;
+				case ParseReason.HighlightBraces:
+				case ParseReason.MatchBraces: return MatchBraces(request);
 			}
 
 			NemerleSource source = (NemerleSource)GetSource(request.View);
@@ -100,22 +100,30 @@
 			return GetDefaultScope(request);
 		}
 
+		#endregion
+
+		#region MatchBraces
+
+		#region MatchBraces()
 
-		private void MatchBraces(ParseRequest request)
+		private AuthoringScope MatchBraces(ParseRequest request)
 		{
-			// Çàäà÷à: 
-			// 1. Íàéòè òîêåí íà êîòîðîì íàõîäèòñÿ êóðñîð.
-			// 2. Îïðåäåëèòü ÷òî ýòî ïàðíûé òîêåí.
-			// 3. Îïðåäåëèòü êàêîé òîêåí ÿâëÿåòñÿ îòâåòíûì.
-			// 4. Íàéòè îòâåòíûé òîêåí â ôàéëå (èñòî÷íèêå).
-			// 5. Ïåðåìåñòèòü êóðñîð íà ýòîò òîêåí.
+			if (!request.Sink.BraceMatching)
+				return GetDefaultScope(request);
 
-			#region Init
+			// Steps: 
+			// 1. Find token under text caret.
+			// 2. Determine that it is a paired token.
+			// 3. Determine paired token.
+			// 4. Find paired token in the source file.
+			// 5. Set info about paired tokens Sink and return it in AuthoringScope.
+
+			#region Init vars
 
 			ProjectInfo projectInfo = GetProjectInfo(request);
 
 			if (projectInfo == null)
-				return;
+				return GetDefaultScope(request);
 
 			NemerleSource source = projectInfo.GetSource(request.FileName);
 			IVsTextColorState colorState = source.ColorState;
@@ -126,23 +134,49 @@
 
 			#endregion
 
-			// 1. Íàéòè òîêåí íà êîòîðîì íàõîäèòñÿ êóðñîð.
+			// Steps: 1-3
 			BracketFinder bracketFinder = new BracketFinder(source, request.Line + 1, 
 				request.Col + 1, scanner, colorState);
 
+			// 4. Find paired token in the source file.
 			ScanTokenInfo matchBraceInfo = bracketFinder.FindMatchBraceInfo();
 
 			if (matchBraceInfo != null)
 			{
-				GotoLocation(matchBraceInfo.Token.Location);
-				// Ïåðåéòè ê ïîçèöèè (?, matchBraceInfo.Token.Location.Column)
+				// 5. Set info about paired tokens Sink and return it in AuthoringScope.
+
+				request.Sink.FoundMatchingBrace = true;
+
+				// Fif a bug in MPF: Correct location of left token.
+				// It need for correct navigation (to left side of token).
+				Token mactTok = matchBraceInfo.Token;
+				Location mactLoc = request.Reason == ParseReason.MatchBraces 
+					&& !BracketFinder.IsOpenToken(mactTok)
+					? mactTok.Location.FromEnd() : mactTok.Location;
+
+				request.Sink.MatchPair( // Set tokens position info
+					Convert(bracketFinder.StartBraceInfo.Token.Location),
+					Convert(mactLoc), 0);
+
+				return new NemerleAuthoringScope(
+					projectInfo, request.Sink, request.FileName,
+					new SourceTextManager(projectInfo.GetSource(request.FileName)));
 			}
+
+			return GetDefaultScope(request); // we don't fing paired token
 		}
 
+		#endregion
+
 		#region BracketFinder class
 
+		/// <summary>
+		/// Helper class which match paired token (brackets, brace, etc.)
+		/// </summary>
 		private class BracketFinder
 		{
+			#region Fields
+			
 			public IVsTextColorState ColorState;
 			public NemerleSource Source;
 			public int StartLine;
@@ -150,75 +184,120 @@
 			public ScanLexer Lex;
 			NemerleScanner Scanner;
 
+			#endregion
+
 			public BracketFinder(NemerleSource source, int startLine,
 				int startCol, NemerleScanner scanner, IVsTextColorState colorState)
 			{
+				#region Init fields
+
 				Scanner = scanner;
 				Source = source;
 				StartLine = startLine;
 				Lex = scanner.GetLexer();
+				Lex.SetFileName(source.GetFilePath());
 				ColorState = colorState;
 
-				StartBraceInfo = Find(GetLineTokens(startLine, true),
+				#endregion
+
+				#region 2. Determine that it is a paired token. 3. Determine paired token.
+				
+				// Get tokens of line under text carret into dynamic array.
+				List<ScanTokenInfo> lineToks = GetLineTokens(startLine, true);
+				// Find index of token which located under text carret.
+				int index = FindIndex(lineToks,
 					delegate(ScanTokenInfo x)
 					{ return x.Token.Location.Contains(startLine, startCol); });
-				//ScanState = ScanState;
+
+				// If index is corret get corresponding token.
+				ScanTokenInfo startBraceInfo = index < 0 ? null : lineToks[index];
+				// Remember it, if token have paired token.
+				if (IsPairedToken(startBraceInfo.Token))
+					StartBraceInfo = startBraceInfo;
+				else
+				{
+					// otherwise try get right-hand token...
+					startBraceInfo = RightHand(lineToks, index);
+					// Remember it, if token have paired token.
+					if (IsPairedToken(startBraceInfo.Token))
+						StartBraceInfo = startBraceInfo;
+				} 
+
+				#endregion
 			}
 
 			public ScanTokenInfo FindMatchBraceInfo()
 			{
-				if (StartBraceInfo == null) // 1. ÎÊ. Òîêåí íàéäåí.
+				if (StartBraceInfo == null)
 					return null;
-				// 2. Îïðåäåëèòü ÷òî ýòî ïàðíûé òîêåí.
-				// 3. Îïðåäåëèòü êàêîé òîêåí ÿâëÿåòñÿ îòâåòíûì.
-				// 4. Íàéòè îòâåòíûé òîêåí â ôàéëå (èñòî÷íèêå).
+
+				// 4. Find paired token in the source file.
 
 				Token tok = StartBraceInfo.Token;
 				Predicate<Token> isStartBrace = GetMatchBracePredicate(tok);
-				Predicate<Token> isEndBrace = GetMatchBracePredicate(GetMatchBrace(tok));
+				Predicate<Token> isEndBrace = GetMatchBracePredicate(GetPairedToken(tok));
 				int nestedLevel = 1;
-				IEnumerable<ScanTokenInfo> iter = GetTokenIter();
-				foreach (ScanTokenInfo tokInfo in iter)
+
+				foreach (ScanTokenInfo tokInfo in GetTokenIter())
 				{
 					if (isEndBrace(tokInfo.Token))
 						nestedLevel--;
 					else if (isStartBrace(tokInfo.Token))
 						nestedLevel++;
 					if (nestedLevel == 0)
-						return tokInfo;
+						return tokInfo; // Match found!
 				}
 
-				return null;
+				return null; // Match not found.
 			}
 
+			#region GetTokenIter()
 
+			/// <summary>
+			/// Return iterator which allow iterate throw tokens of curent 
+			/// source file. Iteration process start from token behind current 
+			/// token and go forward or backward depending on type of start token.
+			/// If start token is open token (for example, "(" or "{") iteration
+			/// execute forward. If start token is close token (for example, ")" 
+			/// or "]") iteration execute backward.
+			/// </summary>
 			private IEnumerable<ScanTokenInfo> GetTokenIter()
 			{
-				bool isScanForward = IsSearchForward(StartBraceInfo.Token);
+				bool isScanForward = IsOpenToken(StartBraceInfo.Token);
 				int startLine = StartLine;
 				// 1. Äëÿ ïåðâîé ñòðîêè íàõîäèì òîêåí è íà÷èíàÿ îò íåãî ñêàíèðóåì âïåðåä èëè íàçàä.
 				List<ScanTokenInfo> tokInfs = new List<ScanTokenInfo>(
 					GetLineTokens(startLine, isScanForward));
-				//TODO: Èñêàòü íóæíî íå ïî àäðåñó, à ïî èíäåêñó, òàê êàê GetLineTokens() âîçâðàùàåò êàêæäûé ðàç íîâûå îáúåêòû.
+
 				int tokIndex = FindIndex(tokInfs, delegate(ScanTokenInfo ti)
 					{ return ti.Token.Location == StartBraceInfo.Token.Location; });
 				if (tokIndex < 0)
 					throw new Exception("tokInfs.IndexOf(startBraceInfo)");
 
-				// Scan first line.
+				// Scan first line from "start bracket" index.
 				for (int i = tokIndex + 1; i < tokInfs.Count; i++)
 					yield return tokInfs[i];
 
-				if (isScanForward)
-					for (int i = startLine + 1, count = Source.GetLineCount(); i < count; i++)
+				if (isScanForward) // Scan next lines.
+					for (int i = startLine + 1, count = Source.GetLineCount(); i <= count; i++)
 						foreach (ScanTokenInfo tokInf in GetLineTokens(i, true))
 							yield return tokInf;
-				else
+				else // Scan previous lines.
 					for (int i = startLine - 1; i >= 0; i--)
 						foreach (ScanTokenInfo tokInf in GetLineTokens(i, false))
 							yield return tokInf;
 			}
 
+			#endregion
+
+			#region GetLineTokens()
+
+			/// <summary>
+			/// Get tokens of specified line.
+			/// </summary>
+			/// <param name="line">Line number which tokens it is necessary retrieve</param>
+			/// <param name="isForward">Direction of iteration (true is forward)</param>
+			/// <returns>Token list</returns>
 			List<ScanTokenInfo> GetLineTokens(int line, bool isForward)
 			{
 				ScanState scanState = GetLineState(line);
@@ -236,6 +315,18 @@
 				return lst;
 			}
 
+			/// <summary>Return colorer lexer state for specified line.</summary>
+			private ScanState GetLineState(int line)
+			{
+				int state;
+				ErrorHandler.ThrowOnFailure(
+					ColorState.GetColorStateAtStartOfLine(line, out state));
+				return (ScanState)state;
+			}
+
+			/// <summary>
+			/// Imlementation of GetLineTokens(). Don't use this method directly!
+			/// </summary>
 			IEnumerable<ScanTokenInfo> GetLineTokens(ScanLexer lex, ScanState scanState)
 			{
 				ScanTokenInfo info = lex.GetToken(scanState);
@@ -248,15 +339,11 @@
 				}
 			}
 
-			private ScanState GetLineState(int line)
-			{
-				int state;
-				ErrorHandler.ThrowOnFailure(
-					ColorState.GetColorStateAtStartOfLine(line, out state));
-				return (ScanState)state;
-			}
+			#endregion
+
+			#region Paired token identification functions
 
-			private static bool IsSearchForward(Token token)
+			public static bool IsOpenToken(Token token)
 			{
 				if (token is Token.BeginBrace) return true;
 				if (token is Token.BeginQuote) return true;
@@ -268,9 +355,37 @@
 				if (token is Token.EndRound) return false;
 				if (token is Token.EndSquare) return false;
 
+				Token.Keyword kwd = token as Token.Keyword;
+
+				if (kwd != null)
+				{
+					if (kwd.name == "if") return true;
+					if (kwd.name == "else") return false;
+				}
+
 				throw new Exception("The token '" + token + "' not a brace!");
 			}
 
+			private static bool IsPairedToken(Token token)
+			{
+				if (token is Token.BeginBrace || token is Token.BeginQuote
+					|| token is Token.BeginRound || token is Token.BeginSquare
+					|| token is Token.EndBrace || token is Token.EndQuote
+					|| token is Token.EndRound || token is Token.EndSquare
+				)
+					return true;
+
+				Token.Keyword kwd = token as Token.Keyword;
+
+				if (kwd != null && (kwd.name == "if" || kwd.name == "else"))
+					return true;
+
+				return false;
+			}
+
+			/// <summary>
+			/// Return predicate function which check it argument is same token .
+			/// </summary>
 			private static Predicate<Token> GetMatchBracePredicate(Token token)
 			{
 				if (token is Token.BeginBrace)
@@ -291,10 +406,36 @@
 				if (token is Token.EndSquare)
 					return delegate(Token t) { return t is Token.EndSquare; };
 
+				Token.Keyword kwd = token as Token.Keyword;
+
+				if (kwd != null)
+				{
+					if (kwd.name == "if")
+						return delegate(Token t)
+						{
+							Token.Keyword kwd1 = t as Token.Keyword;
+
+							if (kwd1 != null)
+								return kwd1.name == "if";
+
+							return false;
+						};
+					if (kwd.name == "else")
+						return delegate(Token t)
+						{
+							Token.Keyword kwd1 = t as Token.Keyword;
+
+							if (kwd1 != null)
+								return kwd1.name == "else";
+
+							return false;
+						};
+				}
+
 				return null;
 			}
 
-			private static Token GetMatchBrace(Token token)
+			private static Token GetPairedToken(Token token)
 			{
 				if (token is Token.BeginBrace) return new Token.EndBrace(true);
 				if (token is Token.BeginQuote) return new Token.EndQuote();
@@ -306,9 +447,30 @@
 				if (token is Token.EndRound) return new Token.BeginRound();
 				if (token is Token.EndSquare) return new Token.BeginSquare();
 
+				Token.Keyword kwd = token as Token.Keyword;
+
+				if (kwd != null)
+				{
+					if (kwd.name == "if")   return new Token.Keyword("else");
+					if (kwd.name == "else") return new Token.Keyword("if");
+				}
+
 				return null;
 			}
 
+			#endregion
+
+			#region Utils
+
+			static T RightHand<T>(IList<T> lst, int index) where T : new()
+			{
+				int nextIndex = index + 1;
+				if (nextIndex >= lst.Count)
+					return new T();
+
+				return lst[nextIndex];
+			}
+
 			private static List<T> Reverce<T>(IEnumerable<T> seq)
 			{
 				List<T> lst = new List<T>(seq);
@@ -333,10 +495,16 @@
 
 				return -1;
 			}
+ 
+			#endregion
 		}
 		
 		#endregion
 
+		#endregion
+
+		#region Check
+
 		private AuthoringScope Check(ParseRequest request)
 		{
 			Trace.WriteLine((string)">>>> ##### Check!");
@@ -390,8 +558,8 @@
 							request.FileName,
 							cm.Message.Replace("`", "'"),
 							ts,
-							cm.MessageKind == MessageKind.Error?   Severity.Error :
-							cm.MessageKind == MessageKind.Warning? Severity.Warning :
+							cm.MessageKind == MessageKind.Error ? Severity.Error :
+							cm.MessageKind == MessageKind.Warning ? Severity.Warning :
 							                                       Severity.Hint);
 
 						return true;
@@ -416,6 +584,10 @@
 			}
 		}
 
+		#endregion
+
+		#region Highlight
+
 		private bool NowIsTerminalSession()
 		{
 			return false;
@@ -452,27 +624,9 @@
 					projectInfo.RemoveLastHighlighting(new SourceTextManager(projectInfo.GetSource(request.FileName)));
 		}
 
-		private AuthoringScope GetMethodScope(ParseRequest request)
-		{
-			HighlightUsages(request);
-
-			string text;
-
-			int res = request.View.GetTextStream(
-				request.Line, request.Col, request.Line, request.Col + 1, out text);
-
-			if (res != VSConstants.S_OK || text.Length == 0 || text[0] == ' ' || text[0] == '\t')
-				return null;
-
-			ProjectInfo projectInfo = GetProjectInfo(request);
-
-			if (projectInfo == null)
-				return null;
+		#endregion
 
-			return new NemerleAuthoringScope(
-				projectInfo, request.Sink, request.FileName,
-				new SourceTextManager(projectInfo.GetSource(request.FileName)));
-		}
+		#region GetCompleteWord
 
 		private AuthoringScope GetCompleteWord(ParseRequest request)
 		{
@@ -499,6 +653,36 @@
 			return GetDefaultScope(request);
 		}
 
+		#endregion
+
+		#region GetMethodScope
+
+		private AuthoringScope GetMethodScope(ParseRequest request)
+		{
+			HighlightUsages(request);
+
+			string text;
+
+			int res = request.View.GetTextStream(
+				request.Line, request.Col, request.Line, request.Col + 1, out text);
+
+			if (res != VSConstants.S_OK || text.Length == 0 || text[0] == ' ' || text[0] == '\t')
+				return null;
+
+			ProjectInfo projectInfo = GetProjectInfo(request);
+
+			if (projectInfo == null)
+				return null;
+
+			return new NemerleAuthoringScope(
+				projectInfo, request.Sink, request.FileName,
+				new SourceTextManager(projectInfo.GetSource(request.FileName)));
+		}
+ 
+		#endregion
+
+		#region GetMethodTip
+
 		private AuthoringScope GetMethodTip(ParseRequest request)
 		{
 			ProjectInfo projectInfo = GetProjectInfo(request);
@@ -523,13 +707,13 @@
 			{
 				if (methods.StartName.EndLine > 0)
 				{
-					request.Sink.StartName      (Convert(methods.StartName), methods.GetName(0));
+					request.Sink.StartName(Convert(methods.StartName), methods.GetName(0));
 					request.Sink.StartParameters(Convert(methods.StartParameters));
 
 					foreach (Location loc in methods.NextParameters)
 						request.Sink.NextParameter(Convert(loc));
 
-					request.Sink.EndParameters  (Convert(methods.EndParameters));
+					request.Sink.EndParameters(Convert(methods.EndParameters));
 				}
 				else
 				{
@@ -551,6 +735,10 @@
 			return GetDefaultScope(request);
 		}
 
+		#endregion
+
+		#region Utils
+
 		private AuthoringScope GetDefaultScope(ParseRequest request)
 		{
 			ProjectInfo projectInfo = ProjectInfo.FindProject(request.FileName);
@@ -587,6 +775,8 @@
 
 		#endregion
 
+		#endregion
+
 		#region Colorizing
 
 		// This array contains the definition of the colorable items provided by



More information about the svn mailing list