[svn] r7640: vs-plugin/trunk: Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj Nemerle.Compiler.Utils/...

kliss svnadmin at nemerle.org
Mon Apr 30 22:54:08 CEST 2007


Log:
Work on formatter.

Author: kliss
Date: Mon Apr 30 22:53:41 2007
New Revision: 7640

Added:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeFormattingStageBase.n
Modified:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeIndentationStage.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeLineBreakingStage.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenStreamFinder.n
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleSource.cs
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleViewFilter.cs

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj	Mon Apr 30 22:53:41 2007
@@ -172,6 +172,9 @@
   <ItemGroup>
     <Compile Include="Nemerle.Completion2\TextManagement\IFileTextMerger.n" />
   </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Nemerle.Completion2\CodeFormatting\CodeFormattingStageBase.n" />
+  </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

Added: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeFormattingStageBase.n
==============================================================================
--- (empty file)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeFormattingStageBase.n	Mon Apr 30 22:53:41 2007
@@ -0,0 +1,126 @@
+using System;
+
+using Nemerle;
+using Nemerle.Compiler;
+using Nemerle.Compiler.Utils;
+
+using SCG = System.Collections.Generic;
+
+namespace Nemerle.Completion2.CodeFormatting
+{
+	
+	public class CodeFormattingStageBase : IFormattingStage
+	{
+    protected class MatchingBrackerFinder
+    {
+      mutable level = 0;
+      mutable tokenTypeToLookFor : Type = null;
+      mutable counterpartTokenType : Type = null;
+      
+      static GetCounterpartTokenType(t : Type) : Type
+      {
+      | bb when bb.Equals(typeof(Token.BeginBrace)) => typeof(Token.EndBrace);
+      | bq when bq.Equals(typeof(Token.BeginQuote)) => typeof(Token.EndQuote);
+      | br when br.Equals(typeof(Token.BeginRound)) => typeof(Token.EndRound);
+      | bs when bs.Equals(typeof(Token.BeginSquare)) => typeof(Token.EndSquare);
+      
+      | eb when eb.Equals(typeof(Token.EndBrace)) => typeof(Token.BeginBrace);
+      | eq when eq.Equals(typeof(Token.EndQuote)) => typeof(Token.BeginQuote);
+      | er when er.Equals(typeof(Token.EndRound)) => typeof(Token.BeginRound);
+      | es when es.Equals(typeof(Token.EndSquare)) => typeof(Token.BeginSquare);
+      | _ => null;
+      }
+      
+      public GetSearchFunc(t : Type) : Token -> bool
+      {
+        tokenTypeToLookFor = GetCounterpartTokenType(t);
+        counterpartTokenType = t;
+        
+        if(tokenTypeToLookFor == null)
+          throw InvalidOperationException($"$(t.Name) is not paired token type.");
+        else
+          IsDesirableToken
+      }        
+      
+      IsDesirableToken(t : Token) : bool
+      {
+        if(t.GetType().Equals(tokenTypeToLookFor))
+        { 
+          if(level == 0)
+            true
+          else
+          {
+            level--; 
+            false;
+          }
+        }
+        else if(t.GetType().Equals(counterpartTokenType))
+        {  
+          level++;
+          false;
+        }
+        else
+          false;
+      }
+    }
+
+    public this(engine : Engine, fileIndex : int)
+    {
+      this.Engine = engine;
+      _fileIndex = fileIndex;
+    }
+    
+    public Engine : Engine
+    {
+      mutable _engine : Engine;
+      get         { ManagerClass.Instance = _engine; _engine; }
+      private set { _engine = value }
+    }
+    
+    mutable _region : Location = Location.Default;
+    protected RegionToFormat : Location
+    {
+      get{ _region }
+      private set { _region = value; }
+    }
+
+    protected _fileIndex : int;
+
+    protected mutable rootNamespaceNode : Decl.Namespace = null;
+    protected _tokenFinder : TokenStreamFinder = TokenStreamFinder();
+    
+    private results : SCG.List.[FormatterResult] = SCG.List.[FormatterResult]();
+    protected AddResult(result : FormatterResult) : void
+    {
+      results.Add(result);
+    }
+    protected GetResults() : SCG.List.[FormatterResult]
+    {
+      results;
+    }
+
+    protected Prepare() : void
+    {
+      results.Clear();
+      
+      // This is PExpr form of document
+      rootNamespaceNode = this.Engine.Project.CompileUnits[_fileIndex];
+      
+      def src = this.Engine.ProjectSources.GetSource(_fileIndex).GetText();
+      def lexer = NonEatingLexer(this.Engine, src, Location(_fileIndex, 1, 1));
+      
+      _tokenFinder.Initialize(lexer.ReadAllTokens());
+    }
+
+    public virtual FormatDocument() : SCG.List.[FormatterResult]
+    {
+      SCG.List.[FormatterResult]();
+    }
+    public virtual FormatRegion(startLine : int, startCol : int, endLine : int, endCol : int) : SCG.List.[FormatterResult]
+    {
+      RegionToFormat = Location(_fileIndex, startLine, startCol, endLine, endCol);
+      SCG.List.[FormatterResult]();
+    }
+	
+	}
+}

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeIndentationStage.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeIndentationStage.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeIndentationStage.n	Mon Apr 30 22:53:41 2007
@@ -1,23 +1,713 @@
 using System;
+using System.Diagnostics;
+using System.Text;
+
 using Nemerle.Utility;
+using Nemerle.Compiler;
+using Nemerle.Compiler.Parsetree;
 
 using SCG = System.Collections.Generic;
 
+/* TODO: Formatter
+ * format comments
+ * format multiline expressions
+ * format macro calls with respect to custom syntax
+ * 
+ *
+ */
+
 namespace Nemerle.Completion2.CodeFormatting
 {
-  public class CodeIndentationStage : IFormattingStage
+  public class CodeIndentationStage : CodeFormattingStageBase
+  {
+    public this (engine : Engine, fileIndex : int)
+    {
+      base(engine, fileIndex);
+    }
+    
+    mutable currentLine = 1;
+    mutable indentStack : list[int] = [];
+    
+    PushIndent() : void
+    {
+      PushIndent(PeekIndent() + defaultIndentSize);
+    }
+    PushIndent(arg : int) : void
+    {
+      indentStack ::= arg;
+    }
+    PopIndent() : int
+    {
+      match(indentStack)
+      {
+      | x :: xs => indentStack = xs; x;
+      | [] => 1 // the first column. 
+      }  
+    }
+    PeekIndent() : int
+    {
+      match(indentStack)
+      {
+      | x :: _ => x;
+      | [] => 1 // the first column. 
+      }  
+    }
+    
+    class IndentPusher : IDisposable
+    {
+      parentClass : CodeIndentationStage;
+      //private this() {}
+      public this(parent :  CodeIndentationStage, indentValue : int)
+      {
+        parentClass = parent;
+        parentClass.PushIndent(indentValue);
+      }
+      
+      public Dispose() : void
+      {
+        _ = parentClass.PopIndent();
+      }
+    }
+    GetIndentPusher() : IndentPusher
+    {
+      IndentPusher(this, PeekIndent() + defaultIndentSize);
+    }
+    GetIndentPusher(arg : int) : IndentPusher
+    {
+      IndentPusher(this, arg);
+    }
+    
+    GetFirstBeginBraceAfterLocation(loc : Location) : Token
+    {
+      GetFirstBeginBraceAfterLocation(loc.EndLine, loc.EndColumn);
+    }
+    GetFirstBeginBraceAfterLocation(line : int, col : int) : Token
+    {
+      _tokenFinder.FindNextIf(line, col, tok => tok is Token.BeginBrace);
+    }
+    GetNextPairedBrace(brace : Token) : Token
+    {
+      def matchFinder = MatchingBrackerFinder().GetSearchFunc(brace.GetType());
+      _tokenFinder.FindNextIf(brace.Location.Line, brace.Location.EndColumn + 1, matchFinder);
+    }
+    
+    public static IsWhiteSpace(this token : Token) : bool
+    {
+      match(token)
+      {
+        | Token.WhiteSpace
+        | Token.Indent
+        | Token.NewLine => true;
+        | _ => false    
+      }
+    }
+    
+    indentValue = " "; // TODO: make it configurable by user.
+    defaultIndentSize = 2;
+    matchCasesIndentOffset = 0; // match cases will be indented by matchCasesIndentOffset * defaultIndentSize
+    matchCasesBodyIndentOffset = 2;
+    variantOptionIndentOffset = 1;
+        
+    
+    IndentLocation(loc : Location) : void
+    {
+      def getIndentString(size)
+      {
+        def builder = StringBuilder(size * indentValue.Length);
+        repeat(size) 
+          _ = builder.Append(indentValue);
+        builder.ToString();
+      }
+
+      def canOperate = !loc.IsEmpty && _tokenFinder.GetLineTokens(loc.Line)
+        .Filter(tok => tok.Location.EndColumn <= loc.Column)
+        .ForAll(_.IsWhiteSpace());
+      def isWithinRange = if(RegionToFormat.IsEmpty) true
+                          else if(RegionToFormat.Contains(loc.Line, loc.Column)) true
+                          else false;
+      when(canOperate && isWithinRange)
+      {
+        def expectedPosition = PeekIndent();  
+        
+        if(expectedPosition != 1)
+          AddResult(FormatterResult.Replace(loc.Line, 1, loc.Column, getIndentString(expectedPosition - 1)));
+        else
+          AddResult(FormatterResult.Erase(loc.Line, 1, loc.Column));
+          
+      }
+    }
+
+    FormatMatchCases(cases : list[MatchCase]) : void
+    {
+      def formatSingleCase(matchCase)
+      {
+        matchCase.patterns.Map(_.Location).Iter(loc =>
+            {
+               def pipe = _tokenFinder.FindPrevIf(loc.Line, loc.Column, _ is Token.Operator("|"));
+               IndentLocation(pipe.Location);
+            });
+
+        using(GetIndentPusher(PeekIndent() + matchCasesBodyIndentOffset * defaultIndentSize))
+        {
+          cases.Map(_.body).Iter(FormatPExpr);
+        }
+      }
+      
+      using(GetIndentPusher(PeekIndent() + matchCasesIndentOffset * defaultIndentSize))
+      {
+        cases.Iter(formatSingleCase);
+      }
+    }
+
+
+    FormatPExpr(pexpr : PExpr) : void
+    {
+      
+      if(pexpr.Location.Line == pexpr.Location.EndLine)
+        IndentLocation(pexpr.Location);
+      else match(pexpr)
+      {
+      | Sequence(exprs) => // Sequence { body : list [PExpr]; }
+            exprs.Iter(FormatPExpr);
+      | Try(body, cases) => // Try { body : PExpr; cases : list [TryCase]; }
+          def beginTryBrace = GetFirstBeginBraceAfterLocation(pexpr.Location.Line, pexpr.Location.Column);
+          IndentLocation(pexpr.Location);
+          IndentLocation(beginTryBrace.Location);
+          
+          using(GetIndentPusher())
+          {
+            FormatPExpr(body);
+          } 
+                              
+          def endTryBrace = GetNextPairedBrace(beginTryBrace);
+          IndentLocation(endTryBrace.Location);
+          
+          def catchKeyword = _tokenFinder.FindNextIf(endTryBrace.Location.Line, endTryBrace.Location.Column, _ is Token.Keyword("catch")); 
+          def beginCatchBrace = GetFirstBeginBraceAfterLocation(catchKeyword.Location);
+          def endCatchBrace = GetNextPairedBrace(beginCatchBrace);
+          IndentLocation(catchKeyword.Location);
+          IndentLocation(beginCatchBrace.Location);
+          
+          //cases.Map(_.Location).Iter(WriteLocation);
+          cases.Iter(FormatTryCase);
+
+          IndentLocation(endCatchBrace.Location);
+            
+      | TryFinally(body, handler) => // TryFinally { body : PExpr; handler : PExpr; }
+          def beginTryBrace = GetFirstBeginBraceAfterLocation(pexpr.Location.Line, pexpr.Location.Column);
+          IndentLocation(pexpr.Location);
+          IndentLocation(beginTryBrace.Location);
+                    
+          using(GetIndentPusher())
+          {
+            FormatPExpr(body);
+          } 
+
+          def endTryBrace = GetNextPairedBrace(beginTryBrace);
+          IndentLocation(endTryBrace.Location);
+          
+          def finallyKeyword = _tokenFinder.FindNextIf(endTryBrace.Location.Line, endTryBrace.Location.Column, _ is Token.Keyword("finally")); 
+          def beginFinallyBrace = GetFirstBeginBraceAfterLocation(finallyKeyword.Location);
+          def endFinallyBrace = GetNextPairedBrace(beginFinallyBrace);
+          IndentLocation(finallyKeyword.Location);
+          IndentLocation(beginFinallyBrace.Location);
+          
+          using(GetIndentPusher())
+          {
+            FormatPExpr(handler);
+          } 
+          
+          IndentLocation(endFinallyBrace.Location);
+            
+      | MacroCall(_, ns, parms) as macroExpr => // MacroCall       { name : Name; ns : NamespaceTree.Node; parms : list [SyntaxElement]; }
+          match(ns.Value)
+          {
+          | NamespaceTree.TypeInfoCache.MacroCall (m) =>
+            def (rules, _) = m.SyntaxExtension ();
+            mutable parms_left = parms;
+            //def rules = rules.Next;
+            mutable firstKeywordLoc = None();
+            
+            def formatExpression(pexpr : PExpr)
+            {
+            | PExpr.Sequence(body) as seq =>
+                def beginBrace = _tokenFinder.FindAt(seq.Location.Line, seq.Location.Column);
+                assert(beginBrace is Token.BeginBrace);
+                IndentLocation(beginBrace.Location);
+                
+                using(GetIndentPusher())
+                {
+                  body.Iter(FormatPExpr);
+                }
+                
+                IndentLocation(GetNextPairedBrace(beginBrace).Location);
+            | _ => 
+                using(GetIndentPusher())
+                {
+                  FormatPExpr(pexpr);
+                }
+            }
+            def processSyntaxRules (x) 
+            {
+              match (x) 
+              {
+                | GrammarElement.Keyword (k) => 
+                    def kw = _tokenFinder.FindNextIf(macroExpr.Location.Line,
+                                                     macroExpr.Location.Column,
+                                                     fun(tok : Token) 
+                                                     {
+                                                     | Token.Keyword as a when a.name == k => true
+                                                     | _ => false;
+                                                     });
+                    match(firstKeywordLoc)
+                    {
+                    | None => firstKeywordLoc = Some(kw.Location);
+                    | _ => ()
+                    }
+                    using(GetIndentPusher(firstKeywordLoc.UnSome().Column))
+                    {
+                      IndentLocation(kw.Location);
+                    }
+                    
+                //| GrammarElement.Operator (")") => acc.Write (") ")
+                //| GrammarElement.Operator ("}") => acc.Write ("} ")                
+                //| GrammarElement.Operator (o) => acc.Write (o)
+                //| GrammarElement.Optional (g) => print_gel (g)
+                //| GrammarElement.RawToken => 
+                  //match (parms_left) {
+                    //| SyntaxElement.RawToken (t) :: xs =>
+                      //acc.Write (t.ToString ());
+                      //parms_left = xs;
+                    //| _ =>
+                      //Message.Error ("expected raw token as parameter of macro "
+                                     //+ namespc.GetDisplayName ())
+                  //};
+  //
+                | GrammarElement.Expression =>
+                  match (parms_left) {
+                    | SyntaxElement.Expression (e) :: xs =>
+                      //def beginBrace = GetFirstBeginBraceAfterLocation(e.Location.Line, e.Location.Column);
+                      //IndentLocation(beginBrace.Location);
+                      formatExpression(e);
+                      //IndentLocation(GetNextPairedBrace(beginBrace).Location);
+                      parms_left = xs;
+                    | _ => ()
+                  };
+                | GrammarElement.Parameter =>
+                  match (parms_left) 
+                  {
+                    | SyntaxElement.Parameter (p) :: xs =>
+                      IndentLocation(p.Location);
+                      parms_left = xs;
+                    | _ => ()
+                  }
+
+                //| GrammarElement.ExpressionList =>
+                  //SeparatedCalls (", ", parms_left, fun (_) {
+                    //| SyntaxElement.Expression (e) => SprintExpr (ctx, e, indentation, acc)
+                    //| _ =>
+                      //Message.Error ("expected expression in macro parameters: "
+                                     //+ namespc.GetDisplayName ())
+                  //}, acc);
+  //
+                //| GrammarElement.Branch | GrammarElement.End => Util.ice ("invalid node");
+                | _ => ()
+              }
+              when (x.Next != null)
+                processSyntaxRules (x.Next)
+            }
+            processSyntaxRules(rules);
+          | _ => ()
+          }
+          
+
+      | Match(_, cases) => // Match { expr : PExpr; cases : list [MatchCase]; }
+          def beginBrace = GetFirstBeginBraceAfterLocation(pexpr.Location.Line, pexpr.Location.Column);
+          IndentLocation(pexpr.Location);
+          IndentLocation(beginBrace.Location);
+          
+          FormatMatchCases(cases);
+          
+          def endBrace = GetNextPairedBrace(beginBrace);
+          IndentLocation(endBrace.Location);
+      | DefFunctions(funcs) => // DefFunctions { funs : list [Function_decl]; }
+          foreach(func in funcs)
+          {
+            def kw = _tokenFinder.FindPrevIf( func.header.Location.Line,
+                                              func.header.Location.Column,
+                                              tok => match(tok)
+                                                     {
+                                                     | Token.Keyword("def")
+                                                     | Token.Keyword("and") => true;
+                                                     | _ => false;
+                                                     });
+            IndentLocation(kw.Location);
+            def beginBrace = GetFirstBeginBraceAfterLocation(func.header.Location);
+            IndentLocation(beginBrace.Location);
+            
+            match(func.body)
+            {
+            | PExpr.Match(_, cases) => FormatMatchCases(cases);
+            | expr => 
+                using(GetIndentPusher())
   {
-    public this (_engine : Engine, _fileIndex : int)
+                  FormatPExpr(expr);  
+                }
+            }
+            
+            IndentLocation(GetNextPairedBrace(beginBrace).Location);
+          }
+      | Lambda(_) => // Lambda { decl : Function_decl; }
+          ()
+          //IndentLocation(lambda.header.Location);
+          //def formatBodyAfter(loc)
+          //{
+          //  def tok = _tokenFinder.FindNextIf(loc.EndLine, loc.EndColumn, FirstNonWhitespaceToken);
+          //  match(tok)
+          //  {
+          //  | BeginBrace =>
+          //      IndentLocation(tok.Location);
+          //      using(GetIndentPusher())
+          //      {
+          //        FormatPExpr(lambda.body);
+          //      }
+          //      IndentLocation(GetNextPairedBrace(tok).Location);
+          //  | Operator("=>") => formatBodyAfter(tok.Location);
+          //  | _ => 
+          //      using(GetIndentPusher())
+          //      {
+          //        FormatPExpr(lambda.body);
+          //      } 
+          //  }
+          //}
+          //formatBodyAfter(lambda.header.Location);
+          
+      | Define (name, val)
+      | DefMutable(name, val) =>
+          def kw = _tokenFinder.FindPrevIf( name.Location.Line,
+                                            name.Location.Column,
+                                            tok => match(tok)
+                                                   {
+                                                   | Token.Keyword("def")
+                                                   | Token.Keyword("mutable") => true;
+                                                   | _ => false;
+                                                   });
+          IndentLocation(kw.Location);
+          FormatPExpr(name);
+
+          def equalSign = _tokenFinder.FindNextIf(name.Location.EndLine, name.Location.EndColumn, _ is Token.Operator("="));
+          using(GetIndentPusher(equalSign.Location.EndColumn + 1))
+          {
+            FormatPExpr(val);
+          }
+          
+      | Assign (name, val) =>
+          FormatPExpr(name);
+
+          def equalSign = _tokenFinder.FindNextIf(name.Location.EndLine, name.Location.EndColumn, _ is Token.Operator("="));
+          using(GetIndentPusher(equalSign.Location.EndColumn + 1))
+          {
+            FormatPExpr(val);
+          }
+      //| Indexer (obj, parms) 
+      | Call(obj, parms)  => // here obj is the func name.
+          FormatPExpr(obj);
+          using(GetIndentPusher(parms.Head.Location.Column + defaultIndentSize))
+          {
+            parms.Iter(FormatPExpr);  
+          }
+      | Member(obj, member) =>
+          FormatPExpr(obj);
+          def dot = _tokenFinder.FindNextIf(obj.Location.EndLine, obj.Location.EndColumn, _ is Token.Operator("."));
+          using(GetIndentPusher())
+          {
+            IndentLocation(dot.Location);
+            FormatSplicable(member);
+          }
+      | ListLiteral (elems) =>
+          def beginBracket = _tokenFinder.FindNextIf(pexpr.Location.Line, pexpr.Location.Column, _ is Token.BeginSquare);
+          IndentLocation(beginBracket.Location);
+          using(GetIndentPusher())
+          {
+            elems.Iter(FormatPExpr);
+          }
+          IndentLocation(GetNextPairedBrace(beginBracket).Location);
+
+      | _ => Debug.WriteLine($"Unhandled PExpr, $(pexpr.ToString())");   
+      }
+    } 
+    
+/* Unhandled PExpr's
+    | Wildcard        // _ used mainly in patterns, but also in _ = ignored
+    | Void            // void used only in types
+    | As              { pat : PExpr; name : Splicable; }
+    | Is              { pat : PExpr; ty : PExpr; }
+    | Where           { name : PExpr; fields : PExpr; }
+
+    | Ref             { name : Name; }
+    | GenericSpecifier { func : PExpr; generic_parms : list [PExpr]; }
+    | Throw           { exn : PExpr; }
+    | Literal         { val : Nemerle.Compiler.Literal; }
+    | This
+    | Base
+    | Typeof          { ty : PExpr; }
+    | TypeConversion  { expr : PExpr; ty : PExpr; }  // (expr :> ty)
+    | TypeEnforcement { expr : PExpr; ty : PExpr; } // (expr : ty)
+    | Tuple           { args : list [PExpr]; }
+    | Array           { rank : PExpr; args : PExpr; }
+    | EmptyArray      { sizes : list [PExpr]; }
+    | ParmByRef       { parm : PExpr; }
+    | ParmOut         { parm : PExpr; }
+
+    | Error // placeholder of missing tree (where some errors occured)
+      
+    // macros stuff    
+    | Quoted          { body : SyntaxElement; }
+    | Spliced         { body : PExpr; }
+    | ToComplete      { body : Name; }
+    | Ellipsis        { body : PExpr; }
+    | Typed           { body : Typedtree.TExpr; }
+    | TypedPattern    { body : Typedtree.Pattern; }  
+    | TypedType       { body : TyVar; }
+
+*/   
+    FormatSplicable(name : Splicable) : void
+    {
+    | Name (body) 
+    | HalfId(body)  => IndentLocation(body.Location);
+    | Expression(expr) => FormatPExpr(expr);
+    }
+
+    FormatTryCase(tryCase : TryCase) : void
+    {
+      def pipe = _tokenFinder.FindPrevIf(tryCase.Location.Line, tryCase.Location.Column, _ is Token.Operator("|"));
+      IndentLocation(pipe.Location);
+      
+      match(tryCase)
+      {
+      | Catch(_, exn_ty, handler) => 
+          FormatPExpr(exn_ty);
+          using(GetIndentPusher(PeekIndent() + matchCasesBodyIndentOffset * defaultIndentSize))
+          {
+            FormatPExpr(handler);
+          }
+      | Filter(_, exn_ty, filter, handler) => 
+          FormatPExpr(exn_ty);
+          FormatPExpr(filter);
+          using(GetIndentPusher(PeekIndent() + matchCasesBodyIndentOffset * defaultIndentSize))
+          {
+            FormatPExpr(handler);
+          }
+      | Ellipsis(body) => 
+          using(GetIndentPusher(PeekIndent() + matchCasesBodyIndentOffset * defaultIndentSize))
+          {
+            FormatPExpr(body);
+          }
+      }
+    } 
+
+    FormatMethod(mb : MethodBuilder) : void
+    {
+      // Skipping properties (other methods too?)
+      when((mb.Attributes & NemerleAttributes.SpecialName) == 0)
+      {
+        // TODO: Format header properly (handle multiline headers)
+        IndentLocation(mb.Location);
+
+        def beginBrace = GetFirstBeginBraceAfterLocation(mb.GetHeader().Location);
+        IndentLocation(beginBrace.Location);
+        
+        match(mb.BodyParsed)
+        {
+        | PExpr.Match(_, cases) => FormatMatchCases(cases);
+        | expr => 
+            using(GetIndentPusher())
+            {
+              FormatPExpr(expr);  
+            }
+        }
+        
+        IndentLocation(GetNextPairedBrace(beginBrace).Location);
+      }
+    }
+    
+    FormatProperty(pb : PropertyBuilder) : void
+    {
+      def formatInternal(method : MethodBuilder, kwPredicate)
+      {
+        when(method != null)
+        {
+          def kw = _tokenFinder.FindNextIf( method.Location.Line, 
+                                            method.Location.Column,
+                                            kwPredicate);
+          IndentLocation(kw.Location);
+          
+          def beginBrace = GetFirstBeginBraceAfterLocation(kw.Location);
+          IndentLocation(beginBrace.Location);
+          
+          using(GetIndentPusher())
+          {
+            FormatPExpr(method.BodyParsed);
+          }
+          
+          IndentLocation(GetNextPairedBrace(beginBrace).Location);  
+        }    
+      }
+
+      IndentLocation(pb.Location);
+      def beginBrace = GetFirstBeginBraceAfterLocation(pb.Ast.name.Location);
+      IndentLocation(beginBrace.Location);
+
+      using(GetIndentPusher())
+      {
+        formatInternal(pb.GetGetter() :> MethodBuilder, _ is Token.Identifier("get"));
+        formatInternal(pb.GetSetter() :> MethodBuilder, _ is Token.Identifier("set"));
+      }
+      
+      IndentLocation(GetNextPairedBrace(beginBrace).Location);
+    }
+    
+    FormatField(fb : FieldBuilder) : void
     {
+      Debug.Assert(fb.Location.Line == fb.Location.EndLine, $"Declaration of field $(fb.Name) spans over several lines. Can't indent.");
+      IndentLocation(fb.Location);
+    }
     
+    FormatEvent(eb : EventBuilder) : void
+    {
+      Debug.Assert(eb.Location.Line == eb.Location.EndLine, $"Declaration of event $(eb.Name) spans over several lines. Can't indent.");
+      IndentLocation(eb.Location);
     }
     
-    public FormatDocument() : SCG.List.[FormatterResult]
+    FormatVariantOption(variantOption : TypeBuilder) : void
+    {
+      def pipe = _tokenFinder.FindPrevIf(variantOption.Location.Line, variantOption.Location.Column, _ is Token.Operator("|"));
+      IndentLocation(pipe.Location);
+      
+      def members = variantOption.GetDirectMembers();
+      def hasFields = ! members.ForAll(member => member.Location.IsGenerated); 
+      when(hasFields)
+      {
+        using(GetIndentPusher(PeekIndent() + defaultIndentSize * variantOptionIndentOffset))
+        {
+          def beginBrace = GetFirstBeginBraceAfterLocation(variantOption.Location.Line, variantOption.Location.Column);
+          IndentLocation(beginBrace.Location);
+          using(GetIndentPusher())
+          {
+            foreach(member in members)
+              FormatTypeBuilderMember(member);
+          }
+          IndentLocation(GetNextPairedBrace(beginBrace).Location);
+        }
+          
+      }
+    }
+
+    FormatTypeBuilderMember(member : IMember) : void
+    {
+    | mmb is MemberBuilder => // fields, properties, methods, events
+        unless(mmb.IsGenerated)
+        {
+          match(mmb)
+          {
+          | mb is MethodBuilder => FormatMethod(mb);
+          | pb is PropertyBuilder => FormatProperty(pb);
+          | fb is FieldBuilder => FormatField(fb);
+          | eb is EventBuilder => FormatEvent(eb);
+          | _ => Debug.WriteLine($"!!! Unhandled MemberBuilder type in FormatClassMember: $(mmb.GetType().Name)");  
+          }
+        }
+    | tb is TypeBuilder =>  if(tb.IsVariantOption) 
+                              FormatVariantOption(tb)
+                            else
+                              FormatType(tb);
+    | _ => Debug.WriteLine($"!!! Unhandled member type in FormatClassMember: $(member.GetType().Name)");  
+    }
+    
+    FormatType(tb : TypeBuilder) : void
+    {
+      unless(tb.Location.IsGenerated)
     {
-      SCG.List.[FormatterResult]();
+        def part = match(tb.AstParts.Find(part => part.Location.FileIndex == _fileIndex))
+                    {
+                    | Some(val) => val
+                    | None => throw ApplicationException($"No type part found in file $_fileIndex");
+                    };
+        
+        // TODO: Format base class and implemented interfaces list.
+        
+        IndentLocation(tb.Location);
+        def beginBrace = GetFirstBeginBraceAfterLocation(part.name.Location);
+        IndentLocation(beginBrace.Location);
+  
+        PushIndent();
+        
+        foreach(member in tb.GetDirectMembers())
+          FormatTypeBuilderMember(member);
+
+        _ = PopIndent();
+        def endBrace = GetNextPairedBrace(beginBrace);
+        IndentLocation(endBrace.Location);
+      }
+    }
+    
+    FormatUsing(us : Decl.Using) : void
+    {
+      IndentLocation(us.Location);
+    }
+    
+    FormatNamespace(ns : Decl.Namespace) : void
+    {
+      def beginBrace = GetFirstBeginBraceAfterLocation(ns.Location.Line, ns.Location.Column);
+      mutable isGlobalNS = false;
+      match(ns.Name)
+      {
+      | _ :: _ => // if namespace name isn't empty (not global namespace)
+          IndentLocation(ns.Location);
+          when(beginBrace.Location.Line > ns.Location.Line) // assume that namespace name is single-lined.
+            IndentLocation(beginBrace.Location);
+      | _ => isGlobalNS = true;
+      }
+      unless(isGlobalNS)
+        PushIndent();
+      
+      foreach(x in ns.Decls)
+      {
+        match(x)
+        {
+          | Decl.Namespace as n => FormatNamespace(n);
+          | Decl.Type as t => FormatType(t.Builder);
+          | Decl.Using as u => FormatUsing(u);
+          | _ => ()
+        }
+      }
+
+      unless(isGlobalNS)
+      {
+        _ = PopIndent();
+        def endBrace = GetNextPairedBrace(beginBrace);
+        IndentLocation(endBrace.Location);
+      }
+    }
+
+    _WriteLocation(loc : Location) : void
+    {
+      Debug.WriteLine($"Location: $(loc.Line), $(loc.Column), $(loc.EndLine), $(loc.EndColumn)");
+    }
+    
+    public override FormatDocument() : SCG.List.[FormatterResult]
+    {
+      Prepare();
+      
+      //def preparser = PreParser(lexer);
+      //_documentTokens = preparser.PreParse();
+      //
+      FormatNamespace(rootNamespaceNode);
+      GetResults();
     }
-    public FormatRegion(_startLine : int, _startCol : int, _endLine : int, _endCol : int) : SCG.List.[FormatterResult]
+    public override FormatRegion(startLine : int, startCol : int, endLine : int, endCol : int) : SCG.List.[FormatterResult]
     {
+      _ = base.FormatRegion(startLine, startCol, endLine, endCol);
       FormatDocument();
     }
   }

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeLineBreakingStage.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeLineBreakingStage.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/CodeLineBreakingStage.n	Mon Apr 30 22:53:41 2007
@@ -12,80 +12,16 @@
 namespace Nemerle.Completion2.CodeFormatting
 {
 
-  class CodeLineBreakingStage : IFormattingStage
+  class CodeLineBreakingStage : CodeFormattingStageBase
   {
-    class MatchingBrackerFinder
-    {
-      mutable level = 0;
-      mutable tokenTypeToLookFor : Type = null;
-      mutable counterpartTokenType : Type = null;
-      
-      static GetCounterpartTokenType(t : Type) : Type
-      {
-      | bb when bb.Equals(typeof(Token.BeginBrace)) => typeof(Token.EndBrace);
-      | bq when bq.Equals(typeof(Token.BeginQuote)) => typeof(Token.EndQuote);
-      | br when br.Equals(typeof(Token.BeginRound)) => typeof(Token.EndRound);
-      | bs when bs.Equals(typeof(Token.BeginSquare)) => typeof(Token.EndSquare);
-      
-      | eb when eb.Equals(typeof(Token.EndBrace)) => typeof(Token.BeginBrace);
-      | eq when eq.Equals(typeof(Token.EndQuote)) => typeof(Token.BeginQuote);
-      | er when er.Equals(typeof(Token.EndRound)) => typeof(Token.BeginRound);
-      | es when es.Equals(typeof(Token.EndSquare)) => typeof(Token.BeginSquare);
-      | _ => null;
-      }
-      
-      public GetSearchFunc(t : Type) : Token -> bool
-      {
-        tokenTypeToLookFor = t;
-        // TODO: Check if t is paired token
-        counterpartTokenType = GetCounterpartTokenType(t);
-        IsDesirableToken
-      }        
-      
-      IsDesirableToken(t : Token) : bool
-      {
-        if(t.GetType().Equals(tokenTypeToLookFor))
-        { 
-          if(level == 0)
-            true
-          else
-          {
-            level--; 
-            false;
-          }
-        }
-        else if(t.GetType().Equals(counterpartTokenType))
-        {  
-          level++;
-          false;
-        }
-        else
-          false;
-      }
-    }
-    
-    public Engine : Engine
-    {
-      mutable _engine : Engine;
-      get         { ManagerClass.Instance = _engine; _engine; }
-      private set { _engine = value }
-    }
-
-    mutable _fileIndex : int;
     
     mutable _startLine = 0;
     mutable _endLine = 0;
     
-    mutable _results : SCG.List.[FormatterResult];
-    indentSize = 2;
     mutable _expectedLine = 1;
-    mutable _expectedCol = -1;
 
     mutable _insertedLines = 0;
     
-    mutable _documentTokens : Token;
-    mutable _tokenFinder : TokenStreamFinder = null;
-
     SetExpectedLine(val : int) : void
     {
       _expectedLine = val;
@@ -97,7 +33,7 @@
     
     LineBreak(loc : Location) : void
     {
-      _results.Add(FormatterResult.Insert(loc.Line, loc.Column, Environment.NewLine));
+      AddResult(FormatterResult.Insert(loc.Line, loc.Column, Environment.NewLine));
     }
     
     NeededLineBreaks(loc : Location) : int
@@ -109,12 +45,6 @@
       };
     }
     
-    IsBeginBrace(token : Token) : bool
-    {
-    | BeginBrace => true
-    | _ => false
-    }
-    
     #endregion
     
     FormatBrace(token : Token) : void
@@ -131,7 +61,8 @@
     
     FormatNamespace(ns : Decl.Namespace) : void
     {
-      def beginBrace = _tokenFinder.FindNextIf(ns.Location.Line, ns.Location.Column, IsBeginBrace);
+      def beginBrace = _tokenFinder.FindNextIf(ns.Location.Line, ns.Location.Column, tok => tok is Token.BeginBrace);
+      
       match(ns.Name)
       {
       | _ :: _ => // if namespace name isn't empty (not global namespace)
@@ -139,7 +70,7 @@
           FormatBrace(beginBrace);
       | _ => ();
       }
-      _expectedCol += indentSize;
+      
       foreach(x in ns.Decls)
       {
         match(x)
@@ -150,7 +81,6 @@
           | _ => ()
         }
       }
-      _expectedCol -= indentSize;
       // TODO: Format end brace here.
       
     }
@@ -172,14 +102,14 @@
       unless(mb.IsGenerated)
       {
         SetExpectedLine(mb.Header.Location.EndLine + 1);
-        def beginBrace = _tokenFinder.FindNextIf(mb.Header.Location.EndLine, mb.Header.Location.EndColumn, IsBeginBrace);
+        def beginBrace = _tokenFinder.FindNextIf(mb.Header.Location.EndLine, mb.Header.Location.EndColumn, tok => tok is Token.BeginBrace);
         FormatBrace(beginBrace);
 
         // TODO: Format every expression
 
         def matchFinder = MatchingBrackerFinder().GetSearchFunc(typeof(Token.EndBrace));
         def endBrace = _tokenFinder.FindNextIf(beginBrace.Location.Line, beginBrace.Location.EndColumn, matchFinder);
-        _results.Add(FormatterResult.Insert(endBrace.Location.Line, endBrace.Location.Column, "/*endBrace*/"));   
+        AddResult(FormatterResult.Insert(endBrace.Location.Line, endBrace.Location.Column, "/*endBrace*/"));   
         FormatBrace(endBrace);
 
         SetExpectedLine(endBrace.Location.EndLine + 1);
@@ -227,9 +157,11 @@
     | _ => Debug.WriteLine($"!!! Unhandled member type in FormatClassMember: $(member.GetType().Name)");  
     }
     
-    FormatType(_tb : TypeBuilder) : void
+    FormatType(tb : TypeBuilder) : void
     {
-      def part = match(_tb.AstParts.Find(part => part.Location.FileIndex == _fileIndex))
+      unless(tb.Location.IsGenerated)
+      {
+        def part = match(tb.AstParts.Find(part => part.Location.FileIndex == _fileIndex))
                   {
                   | Some(val) => val
                   | None => throw ApplicationException($"No type part found in file $_fileIndex");
@@ -238,10 +170,10 @@
       // TODO: Format base class and implemented interfaces list.
       
       SetExpectedLine(part.name.Location.EndLine + 1);
-      def beginBrace = _tokenFinder.FindNextIf(part.name.Location.EndLine, part.name.Location.EndColumn, IsBeginBrace);
+        def beginBrace = _tokenFinder.FindNextIf(part.name.Location.EndLine, part.name.Location.EndColumn, tok => tok is Token.BeginBrace);
       FormatBrace(beginBrace);
       
-      foreach(member in _tb.GetDirectMembers())
+        foreach(member in tb.GetDirectMembers())
         FormatClassMember(member);
       
       def matchFinder = MatchingBrackerFinder().GetSearchFunc(typeof(Token.EndBrace));
@@ -250,39 +182,30 @@
 
       SetExpectedLine(endBrace.Location.EndLine + 1);
     }
+    }
 
     #region IFormattingStage members
 
     public this(engine : Engine, fileIndex : int)
     {
-      this.Engine = engine;
-      _fileIndex = fileIndex;
-      _results = SCG.List.[FormatterResult]();
+      base(engine, fileIndex);
     }
     
-    public FormatRegion(_startLine : int, _startCol : int, _endLine : int, _endCol : int) : SCG.List.[FormatterResult]
+    public override FormatRegion(startLine : int, startCol : int, endLine : int, endCol : int) : SCG.List.[FormatterResult]
     {
+      _ = base.FormatRegion(startLine, startCol, endLine, endCol);
       FormatDocument();
     }
 
-    public FormatDocument() : SCG.List.[FormatterResult]
+    public override FormatDocument() : SCG.List.[FormatterResult]
     {
-      _results.Clear();
-      
-      // This is PExpr form of document
-      def declNS = this.Engine.Project.CompileUnits[_fileIndex];
-      
-      def src = this.Engine.Sources[_fileIndex];
-      def lexer = NonEatingLexer(this.Engine, src, Location(_fileIndex, 1, 1));
-      //def lexer = LexerString(this.Engine, src, Location(_fileIndex, 1, 1));
-      
-      _tokenFinder = TokenStreamFinder(lexer.ReadAllTokens());
-      
-      def preparser = PreParser(lexer);
-      _documentTokens = preparser.PreParse();
+      Prepare();
       
-      FormatNamespace(declNS);
-      _results;
+      //def preparser = PreParser(lexer);
+      //_documentTokens = preparser.PreParse();
+      //
+      FormatNamespace(rootNamespaceNode);
+      GetResults();
     
     }
     

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n	Mon Apr 30 22:53:41 2007
@@ -10,8 +10,6 @@
 using SCG = System.Collections.Generic;
 using Nemerle.Compiler.Parsetree;
 
-using MsgBox = System.Windows.Forms.MessageBox;
-
 namespace Nemerle.Completion2.CodeFormatting
 {
   public class Formatter
@@ -99,13 +97,13 @@
     public static FormatDocument(engine : Engine, filePath : string) : SCG.List[FormatterResult]
     {
       def fileIndex = engine.Project.CompileUnits.GetFileIndex(filePath);
-      //def instance = Formatter(engine, fileIndex);
       def results = SCG.List.[FormatterResult]();
       
+      def _ = CodeLineBreakingStage(engine, fileIndex);
       def stages : list[IFormattingStage] =  
                     [
-                      CodeLineBreakingStage(engine, fileIndex)
-                      //,CodeIndentationStage(engine, fileIndex)
+                      //CodeLineBreakingStage(engine, fileIndex)
+                      CodeIndentationStage(engine, fileIndex)
                     ];
                     
       // TODO: After each stage send result to the VS,
@@ -120,10 +118,26 @@
     }
     
     // Here we have to find out what piece of AST to analyze
-    public FormatSpan(_startLine : int, _startCol : int, _endLine : int, 
-            _endCol : int, _filePath : string) : SCG.List[FormatterResult]
+    public static FormatSpan( startLine : int, startCol : int, endLine : int, 
+                              endCol : int, engine : Engine, filePath : string) : SCG.List[FormatterResult]
     {
-      SCG.List.[FormatterResult]();
+      def fileIndex = engine.Project.CompileUnits.GetFileIndex(filePath);
+      def results = SCG.List.[FormatterResult]();
+      
+      def stages : list[IFormattingStage] =  
+                    [
+                      //CodeLineBreakingStage(engine, fileIndex)
+                      CodeIndentationStage(engine, fileIndex)
+                    ];
+                    
+      // TODO: After each stage send result to the VS,
+      // and wait for changes to be applied.
+      foreach(stage in stages)
+      {
+        results.AddRange(stage.FormatRegion(startLine, startCol, endLine, endCol)); 
+      }
+
+      results;
     }
   }
 }

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n	Mon Apr 30 22:53:41 2007
@@ -7,7 +7,7 @@
 
 namespace Nemerle.Completion2.CodeFormatting
 {
-  [Record]
+  [Record (Exclude = [ResultType])]
   public class FormatterResult
   {
     [Accessor] _startLine : int = -1;
@@ -15,12 +15,37 @@
     [Accessor] _endLine : int = -1;
     [Accessor] _endCol : int  = -1;
     [Accessor] _replacementString : string = "";
+    public ResultType : string
+    {
+      get
+      {
+        if(StartCol == EndCol)
+        {
+          if(ReplacementString.Length > 0)
+            "Insertion"
+          else
+            "ERROR"
+        }
+        else
+        {
+          if(ReplacementString.Length == 0)
+            "Erase"
+          else
+            "Replacement"
+        } 
+      }
+    }
     
     public static Replace(loc : Location, replacement : string) : FormatterResult 
     {
       FormatterResult(loc.Line, loc.Column, loc.EndLine, loc.EndColumn, replacement);
     }
     
+    public static Replace(line : int, fromCol : int, toCol : int, replacement : string) : FormatterResult
+    {
+      FormatterResult(line, fromCol, line, toCol, replacement);
+    }
+    
     public static Insert(line : int, column : int, value : string) : FormatterResult
     {
       FormatterResult(line, column, line, column, value);
@@ -28,7 +53,12 @@
     
     public static Erase(loc : Location) : FormatterResult
     {
-      FormatterResult(loc.Line, loc.Column, loc.EndLine, loc.EndColumn, "");
+      Replace(loc, "");
+    } 
+    
+    public static Erase(line : int, fromCol : int, toCol : int) : FormatterResult
+    {
+      Replace(line, fromCol, toCol, "");
     } 
   }
 }
\ No newline at end of file

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenStreamFinder.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenStreamFinder.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenStreamFinder.n	Mon Apr 30 22:53:41 2007
@@ -1,7 +1,9 @@
 using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+
 using Nemerle;
 using Nemerle.Compiler;
-using System.Collections.Generic;
 using Nemerle.Completion2.CodeFormatting;
 
 namespace Nemerle.Completion2
@@ -10,10 +12,19 @@
   public class TokenStreamFinder
   {
     _sortedTokens : Dictionary.[int, array[Token]] = Dictionary();
+    mutable isInitialized = false;
+    
+    public this(){}
     
     // We're assuming that tokens are ordered as they appear in the source, i.e. no reversing and shuffling.
     public this(tokens : array[Token])
     {
+      Initialize(tokens);
+    }
+    
+    public Initialize(tokens : array[Token]) : void
+    {
+      isInitialized = true;
       def curLineTokens = List(); 
       
       // Enumerate tokens starting from currentTokenPos and see if they belong 
@@ -56,6 +67,10 @@
     
     public FindNextIf(line : int, col : int, predicate : Token -> bool) : Token
     {
+      if(!isInitialized)
+        throw InvalidOperationException("TokenStreamFinder hasn't been properly initialized. Either use constructor with parameters or Initialize() method.");
+      else
+      {
       mutable curLine = line;
       mutable curIndex = 0;
 
@@ -70,7 +85,7 @@
       {
         if(curIndex < _sortedTokens[curLine].Length - 1)
           curIndex++;
-        else when(_sortedTokens.ContainsKey(curLine + 1))
+          else //when(_sortedTokens.ContainsKey(curLine + 1))
         {
           curLine++;
           curIndex = 0;
@@ -82,6 +97,8 @@
         advancePosition();
         tok
       }
+        when(!_sortedTokens.ContainsKey(curLine))
+          Debug.WriteLine($"No key: $curLine");
       mutable startLineTokens = _sortedTokens[curLine];
       def setStartPoint()
       {
@@ -103,7 +120,7 @@
 
       // Ok, start position defined. Start matching each next token against given predicate.
       mutable result = getNextToken();
-      while(!predicate(result))
+        while(result != null && !predicate(result))
       {
         result = getNextToken();
       }
@@ -111,16 +128,89 @@
         throw TokenNotFoundException("Token not found");
       result;
     }
+    }
     
-    public FindPrevIf(_line : int, _col : int, _predicate : Token -> bool) : Token
+    public FindPrevIf(line : int, col : int, predicate : Token -> bool) : Token
+    {
+      if(!isInitialized)
+        throw InvalidOperationException("TokenStreamFinder hasn't been properly initialized. Either use constructor with parameters or Initialize() method.");
+      else
     {
-      throw NotImplementedException()
+        mutable curLine = line;
+        mutable curIndex = _sortedTokens[curLine].Length - 1;
+
+        def getCurrentToken()
+        {
+          if(curIndex < _sortedTokens[curLine].Length)
+            _sortedTokens[curLine][curIndex]
+          else
+            null
+        }
+        def retreatPosition()
+        {
+          if(curIndex > 0)
+            curIndex--;
+          else //when(_sortedTokens.ContainsKey(curLine - 1))
+          {
+            curLine--;
+            curIndex = _sortedTokens[curLine].Length - 1;
+          }  
+        }
+        def getPrevToken()
+        {
+          def tok = getCurrentToken();
+          retreatPosition();
+          tok
+        }
+        when(!_sortedTokens.ContainsKey(curLine))
+          Debug.WriteLine($"No key: $curLine");
+        mutable startLineTokens = _sortedTokens[curLine];
+        def setStartPoint()
+        {
+          if(curLine == line && curIndex > 0 && startLineTokens[curIndex].Location.Column > col)
+          {
+            curIndex--;
+            setStartPoint();
+          }
+          else when(curIndex == 0)
+          {
+            curLine--;
+            startLineTokens = _sortedTokens[curLine];
+            curIndex = _sortedTokens[curLine].Length - 1;
+            setStartPoint();
+          }
+        }
+        
+        setStartPoint();
+
+        // Ok, start position defined. Start matching each next token against given predicate.
+        mutable result = getPrevToken();
+        while(result != null && !predicate(result))
+        {
+          result = getPrevToken();
+        }
+        when(result == null)
+          throw TokenNotFoundException("Token not found");
+        result;
+      }
     }
     
     public FindAt(line : int, col : int) : Token
     {
+      if(!isInitialized)
+        throw InvalidOperationException("TokenStreamFinder hasn't been properly initialized. Either use constructor with parameters or Initialize() method.");
+      else
+      {
       def lineTokens = _sortedTokens[line];
-      def result = Array.Find(lineTokens, tok => tok.Location.Contains(line, col));
+        def result = Array.Find(lineTokens, tok =>  tok.Location.Contains(line, col)
+                                                    && col != tok.Location.EndColumn);
+        result;
+      }
+    }
+    
+    public GetLineTokens(line : int) : array[Token]
+    {
+      def result = _sortedTokens[line];
       result;
     }
   }

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleSource.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleSource.cs	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleSource.cs	Mon Apr 30 22:53:41 2007
@@ -179,7 +179,13 @@
 		}
         private void ReformatSpan_internal(EditArray _mgr, TextSpan span, Engine engine, string filePath)
         {
-            List<FormatterResult> results = Formatter.FormatDocument(engine, filePath);
+            List<FormatterResult> results =
+                Formatter.FormatSpan(span.iStartLine + 1,
+                           span.iStartIndex + 1,
+                           span.iEndLine + 1,
+                           span.iEndIndex + 1,
+                           engine,
+                           filePath);
             EditArray mgr = new EditArray(_mgr.Source, _mgr.TextView, true, "formatting");
             foreach (FormatterResult res in results)
             {

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleViewFilter.cs
==============================================================================



More information about the svn mailing list