[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