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

kliss svnadmin at nemerle.org
Mon Apr 2 21:08:15 CEST 2007


Log:
1. Added custom colorizing for special comments (TODO, BUG, HACK)
2. Work on code formatter

Author: kliss
Date: Mon Apr  2 21:07:58 2007
New Revision: 7575

Added:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/
   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/NonEatingLexer.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenNotFoundException.n
Removed:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Formatter.n
Modified:
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.csproj
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.nproj
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Checker.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanLexer.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanTokenColor.n
   vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/TokenFinder.n
   vs-plugin/trunk/Nemerle.VsIntegration/CtcComponents/PkgCmd.ctc
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorableItem.cs
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorizer.cs
   vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleLanguageService.cs
   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  2 21:07:58 2007
@@ -49,7 +49,6 @@
     <Compile Include="Nemerle.Completion2\CodeModel\ExprFinder.n" />
     <Compile Include="Nemerle.Completion2\CodeModel\ExprWalkInfo.n" />
     <Compile Include="Nemerle.Completion2\CodeModel\ExprWalker.n" />
-    <Compile Include="Nemerle.Completion2\CodeModel\Formatter.n" />
     <Compile Include="Nemerle.Completion2\CodeModel\GlyphType.n" />
     <Compile Include="Nemerle.Completion2\CodeModel\GotoInfo.n" />
     <Compile Include="Nemerle.Completion2\CodeModel\MethodTipInfo.n" />
@@ -154,6 +153,14 @@
   <ItemGroup>
     <Compile Include="Nemerle.Completion2\TextManagement\MessageType.n" />
   </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Nemerle.Completion2\CodeFormatting\Formatter.n" />
+    <Compile Include="Nemerle.Completion2\CodeFormatting\FormatterResult.n" />
+    <Compile Include="Nemerle.Completion2\CodeFormatting\TokenNotFoundException.n" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Nemerle.Completion2\CodeFormatting\NonEatingLexer.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.

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.nproj
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.nproj	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Compiler.Utils.nproj	Mon Apr  2 21:07:58 2007
@@ -5,6 +5,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Folder Include="Nemerle.Completion2\" />
+    <Folder Include="Nemerle.Completion2\CodeFormatting\" />
     <Folder Include="Nemerle.Completion2\CodeModel\" />
     <Folder Include="Nemerle.Completion2\CompilerConcreteDefinitions\" />
     <Folder Include="Nemerle.Completion2\CompilerConcreteDefinitions\Factories\" />

Added: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n
==============================================================================
--- (empty file)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/Formatter.n	Mon Apr  2 21:07:58 2007
@@ -0,0 +1,287 @@
+using Nemerle.Utility;
+using Nemerle.Compiler;
+using Nemerle.Completion2;
+
+using System;
+using System.Diagnostics;
+using Nemerle.Compiler.Utils;
+using System.Text;
+using System.IO;
+using SCG = System.Collections.Generic;
+using Nemerle.Compiler.Parsetree;
+
+using MsgBox = System.Windows.Forms.MessageBox;
+
+namespace Nemerle.Completion2.CodeFormatting
+{
+  public class Formatter
+  {
+    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;
+    _tokenFinder : TokenFinder = TokenFinder();
+
+    SetExpectedLine(val : int) : void
+    {
+      _expectedLine = val;
+      _insertedLines = 0;
+    }
+
+    
+    public Engine : Engine
+    {
+      mutable _engine : Engine;
+      get         { ManagerClass.Instance = _engine; _engine; }
+      private set { _engine = value }
+    }
+    
+    private this(engine : Engine)
+    {
+      Engine = engine;
+      _results = SCG.List.[FormatterResult]();
+    }
+    
+    #region Helper methods
+    
+    static LineBreakAndIndent(loc : Location, 
+                              indentToColumn : int) : SCG.List.[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult]();
+      def insertion = Environment.NewLine + string(' ', indentToColumn - 1);
+      result.Add(FormatterResult.Insert(loc.Line, loc.Column, insertion));
+      result;
+    }
+
+    static Indent(loc : Location, 
+                  indentToColumn : int) : SCG.List.[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult]();
+      if(loc.Column < indentToColumn)
+      {
+        result.Add(FormatterResult.Insert(loc.Line, loc.Column, string(' ', indentToColumn - loc.Column)));
+      }
+      else when(loc.Column > indentToColumn)
+      {
+        result.Add(FormatterResult.Replace(Location(loc, 
+                                                    loc.Line,
+                                                    indentToColumn,
+                                                    loc.Line,
+                                                    loc.Column),
+                                           ""));  
+      }
+      result;
+    }
+    
+    NeededLineBreaks(loc : Location) : int
+    {
+      match(_expectedLine - (loc.Line + _insertedLines))
+      {
+      | x when x > 0 => x;
+      | _ => 0;
+      };
+    }
+    
+    FindTokenAfter(line : int, col : int, predicate : Token -> bool) : Token
+    {
+      match(_tokenFinder.FindAfter(_documentTokens, line, col, predicate))
+      {
+      | x :: _ => x;
+      | [] => throw TokenNotFoundException("Required token was not found");
+      }
+    }
+    
+    IsBracesGroup(token : Token) : bool
+    {
+    | BracesGroup => true;
+    | _ => false;
+    }
+    
+    
+    
+    #endregion
+    
+    FormatBrace(token : Token) : SCG.List.[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult]();
+
+      def newLineBreaks = NeededLineBreaks(token.Location);
+      if(newLineBreaks > 0)
+      {
+        result.AddRange(LineBreakAndIndent(token.Location, _expectedCol));
+        _insertedLines += 1;
+      }
+      else
+      {
+        result.AddRange(Indent(token.Location, _expectedCol));
+      }
+
+      _expectedLine++;
+      result;
+    }
+    
+    FormatNamespace(ns : Decl.Namespace) : SCG.List[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult]();
+      def body = FindTokenAfter(ns.Location.Line, ns.Location.Column, IsBracesGroup);
+      match(ns.Name)
+      {
+      | _ :: _ => // if namespace name isn't empty (not global namespace)
+          SetExpectedLine(ns.Location.Line + 1);
+          result.AddRange(FormatBrace(body));
+      | _ => ();
+      }
+      _expectedCol += indentSize;
+      foreach(x in ns.Decls)
+      {
+        match(x)
+        {
+          | Decl.Namespace as n => result.AddRange(FormatNamespace(n));
+          | Decl.Type as t => result.AddRange(FormatType(t));
+          | Decl.Using as u => result.AddRange(FormatUsing(u));
+          | _ => ()
+        }
+      }
+      _expectedCol -= indentSize;
+      // TODO: Format end brace here.
+      
+      result;  
+    }
+    
+    mutable static counter : int = 0;
+    FormatUsing(us : Decl.Using) : SCG.List[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult]();
+
+      def newLineBreaks = NeededLineBreaks(us.Location);
+      // TODO: for testing only. To be removed ASAP.
+      //result.Add(FormatterResult.Insert(us.Location.Line, us.Location.Column, $"#define test$(counter)\r\n"));
+      //counter++;
+      //_insertedLines += 1;
+      if(newLineBreaks > 0)
+      {
+        result.AddRange(LineBreakAndIndent(us.Location, _expectedCol));
+        _insertedLines += 1;
+      }
+      else
+      {
+        result.AddRange(Indent(us.Location, _expectedCol));
+        SetExpectedLine(us.Location.Line);
+      }
+
+      _expectedLine++;
+      result; 
+    }
+    
+    FormatType(_tb : Decl.Type) : SCG.List[FormatterResult]
+    {
+      def result = SCG.List.[FormatterResult](); 
+      result; 
+    }
+    
+    _WalkHandler (info : ExprWalkInfo) : void
+    {
+      def node = info.Node;
+      
+      if(node != null)
+      {
+        def loc = if(node is Located) 
+                    (node :> Located).Location 
+                  else if(node is IMember)
+                    (node :> IMember).Location
+                  else if(node is Decl)
+                    (node :> Decl).Location
+                  else
+                    Location.Default;
+        Print(node, loc, 1);
+        
+        match(node)
+        {
+        | pe is PExpr when pe.Location.Line == pe.Location.EndLine =>
+                match(pe)
+                {
+                | PExpr.Define
+                | PExpr.Assign
+                | PExpr.Call
+                | PExpr.Sequence => info.Skip()
+                | _ => ()
+                }
+        | se is SyntaxElement when se.Location.Line == se.Location.EndLine =>
+                info.Skip();
+        | _ => ()
+        }
+      }
+      else
+      {
+        Trace.WriteLine("info.Node is null");
+      }
+    }
+    
+    Print(obj : object, loc : Location, level : int) : void
+    {
+      _ = obj.ToString();
+
+#if DEBUG
+      def indentation = string(' ', level);
+      mutable os = obj.ToString();
+
+      when (os.Length > 200)
+        os = os.Substring(0, 200) + "...";
+
+      Trace.WriteLine("");
+      Trace.WriteLine(indentation + 
+        $"$(obj.GetType().FullName) "
+         "$(loc.Line):$(loc.Column):$(loc.EndLine):$(loc.EndColumn)"
+         "$(if (loc.IsGenerated) '-' else '+')");
+      Trace.WriteLine(indentation + os.Replace("\n", "\n" + indentation));
+#endif
+
+      ignore(obj); ignore(loc); ignore(level);
+    }
+    
+    public static FormatDocument(engine : Engine, filePath : string) : SCG.List[FormatterResult]
+    {
+      def instance = Formatter(engine);
+      def results = SCG.List.[FormatterResult]();
+      
+      // This is PExpr form of document
+      def fileIndex = instance.Engine.Project.CompileUnits.GetFileIndex(filePath);
+      def declNS = instance.Engine.Project.CompileUnits[fileIndex];
+      
+      def src = instance.Engine.Sources[filePath];
+      // And we'll also need document as token groups.
+      def _ = NonEatingLexer(instance.Engine, src, Location(fileIndex, 1, 1));
+      def lexer = LexerString(instance.Engine, src, Location(fileIndex, 1, 1));
+      //lexer.Keywords = lexer.Manager.CoreEnv.Keywords;
+      //
+      //using(def stream = StreamWriter("c:\\tokens.txt"))
+      //{
+      //  foreach(t in lexer.ReadAllTokens())
+      //  {
+      //    stream.WriteLine($"$(t.ToString())\t\t\t$(t.GetType().Name)\t\t\t$(t.Location.Line):$(t.Location.Column):$(t.Location.EndLine):$(t.Location.EndColumn)");
+      //  }
+      //}
+      
+      def preparser = PreParser(lexer);
+      instance._documentTokens = preparser.PreParse();
+      
+      results.AddRange(instance.FormatNamespace(declNS));
+      results;
+    
+    }
+    
+    // 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]
+    {
+      SCG.List.[FormatterResult]();
+    }
+  }
+}

Added: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n
==============================================================================
--- (empty file)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/FormatterResult.n	Mon Apr  2 21:07:58 2007
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Nemerle.Utility;
+using Nemerle.Compiler;
+
+namespace Nemerle.Completion2.CodeFormatting
+{
+  [Record]
+  public class FormatterResult
+  {
+    [Accessor] _startLine : int = -1;
+    [Accessor] _startCol : int = -1;
+    [Accessor] _endLine : int = -1;
+    [Accessor] _endCol : int  = -1;
+    [Accessor] _replacementString : string = "";
+    
+    public static Replace(loc : Location, replacement : string) : FormatterResult 
+    {
+      FormatterResult(loc.Line, loc.Column, loc.EndLine, loc.EndColumn, replacement);
+    }
+    
+    public static Insert(line : int, column : int, value : string) : FormatterResult
+    {
+      FormatterResult(line, column, line, column, value);
+    }    
+    
+    public static Erase(loc : Location) : FormatterResult
+    {
+      FormatterResult(loc.Line, loc.Column, loc.EndLine, loc.EndColumn, "");
+    } 
+  }
+}
\ No newline at end of file

Added: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/NonEatingLexer.n
==============================================================================
--- (empty file)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/NonEatingLexer.n	Mon Apr  2 21:07:58 2007
@@ -0,0 +1,206 @@
+using System;
+using Nemerle;
+using Nemerle.Compiler;
+
+namespace Nemerle.Completion2.CodeFormatting
+{
+  class NonEatingLexer : LexerString
+  {
+    public this (manager : ManagerClass, code : string, loc : Location)
+    {
+      base (manager, code, loc);
+    }
+    
+    protected override do_get_token() : Token
+    {
+      def ch = 
+        if (isPendingChar) 
+        {
+          isPendingChar = false;
+          pendingChar
+        }
+        else 
+        {
+          try { read () }
+          catch { _ is LexerBase.Error => ' ' }
+        }
+      match (ch) 
+      {
+        | '"' => get_string ('"', false)
+
+        | '\'' => get_id ('\'')
+
+        | '.' => 
+          def next = peek_or_white ();
+          if (Char.IsDigit (next))
+            get_number (ch)
+          else if (next == '.') {
+            _ = read ();
+            Token.Operator ("..")
+          } else
+            Token.Operator (".")
+
+        | '{' => Token.BeginBrace (generated = false)
+        | '}' => Token.EndBrace (generated = false)
+        | '[' => Token.BeginSquare ()
+        | ']' =>
+          if (peek_or_white () == '>') 
+          {
+            ignore (read ());
+            Token.EndQuote ()
+          }
+          else
+            Token.EndSquare ()
+        | '(' => Token.BeginRound ()
+        | ')' => Token.EndRound ()
+        | ',' => Token.Comma ()
+        | ';' => Token.Semicolon (generated = false)
+
+        | '<' when peek_or_white () == '[' => ignore (read ()); Token.BeginQuote ()
+          
+        | '@' =>
+          def next = read ();
+          if (next == '#') // Completion token.
+            Token.IdentifierToComplete ("")
+          else if (IsOperatorChar (next))
+            match (get_op (next)) 
+            {
+              | Token.Operator (s) => Token.Identifier (s)
+              | _ => Util.ice ()
+            }
+          else if (IsIdBeginning (next))
+            match (get_id (next)) 
+            {
+              | Token.Identifier (x)
+              | Token.Keyword (x) => Token.QuotedIdentifier (x)
+              | _ => Util.ice ()
+            }
+          else if (next == '"')
+            get_monkey_string ()
+          else
+            throw Error ("expecting operator, identifier or string literal after '@'")
+        
+        | '*' =>
+          if (peek_or_white () == '*')
+            get_op (ch)
+          else
+            get_op (ch)
+
+        | '/' =>
+          get_op (ch)
+                                
+        | '%' | '\\'
+          => get_op (ch)
+
+        | '-' =>
+          if (peek_or_white () != '.') get_op (ch) 
+          else Token.Operator ("-")
+
+        | '+'  
+          =>
+             if (peek_or_white () != '.') get_op (ch) 
+             else Token.Operator ("+")
+
+        | '$' =>
+          //Fake();
+          def startLine = this.Location.Line;
+          def startCol  = this.Location.Column;
+
+          if (eat_whitespace () && (peek_or_white () == '"' || peek_or_white () == '@')) 
+          {
+            // we will not warn about $ in string literal in this mode
+            def strStartLoc = this.Location;
+            def c = read ();
+            
+            def str =
+              if (c == '"')
+                get_string (c, true)
+              else 
+              {
+                unless (read () == '"')
+                  Message.Error (this.Location, "expected string literal after @");
+            
+                get_monkey_string ()
+              }
+
+            def dolLoc = Location(strStartLoc.FileIndex, startLine, startCol - 1, startLine, startCol);
+            str.Location = strStartLoc + str.Location;
+            def groupLok = dolLoc + str.Location;
+            def dolTok = Token.Operator (dolLoc, "$");
+            dolTok.Next = str;
+            Token.RoundGroup (groupLok, Token.LooseGroup (groupLok, dolTok))
+          }
+          else get_op (ch)
+                                
+        | '^' | '~' | '?' | '#'
+          => get_op (ch)
+          
+        | '=' | '<' | '>' | '!' 
+          => get_op (ch)
+          
+        | '&' => get_op (ch)
+        | '|' => get_op (ch)
+        | ':' => get_op (ch)
+
+        // after executing eat_whitespace it is the only possibility for space
+        // (try..catch above)
+        | ' ' => Token.WhiteSpace (" ")
+        | '\t' => Token.Indent ("\t");
+        | '\n' => Token.NewLine("\n");
+        | '\r' => // All three new line styles: Windows, Unix, MacOS
+          if(peek_or_white() == '\n')
+          {
+            ignore(read());
+            Token.NewLine("\r\n");
+          }
+          else
+            Token.NewLine("\r");
+
+        | '\0' => Token.EndOfFile ()
+
+        | _ =>
+          if (Char.IsDigit (ch))
+            get_number (ch)
+          else
+            if (IsIdBeginning (ch))
+              get_id (ch)
+            else
+              throw Error ($"invalid character: `$ch'")
+      }
+    }
+    
+    public override GetToken() : Token
+    {
+      if (tok_pending != null) 
+      {
+        def tok = tok_pending;
+        tok_pending = null;
+        tok
+      } 
+      else 
+      {
+        //unless (isPendingChar)
+          //_ = eat_whitespace ();
+        //
+        if (insert_indent) 
+        {
+          insert_indent = false;
+          Token.Indent (insert_location, indent_string)
+        } 
+        else 
+        {
+          def last_line = line;
+          def last_col = col;
+          def tok = do_get_token ();
+
+          // IT: making last_line & last_col as class fields could be a better solution.
+          if (tok.Location.FileIndex == 0)
+            tok.Location = Location (file_idx, last_line, last_col, line, col);
+          else
+            tok.Location = Location (file_idx, last_line, last_col, tok.Location.EndLine, tok.Location.EndColumn);
+          tok
+        }
+      }
+    }
+  }
+}

Added: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenNotFoundException.n
==============================================================================
--- (empty file)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeFormatting/TokenNotFoundException.n	Mon Apr  2 21:07:58 2007
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Nemerle.Completion2.CodeFormatting
+{
+  public class TokenNotFoundException : Exception
+  {
+    public this(message : string) 
+    {
+      base(message);
+    }
+  }
+}
\ No newline at end of file

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Checker.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Checker.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/Checker.n	Mon Apr  2 21:07:58 2007
@@ -1,4 +1,5 @@
 using System;
+using System.Reflection;
 using System.Diagnostics;
 
 using Nemerle.Collections;
@@ -256,6 +257,8 @@
 
       //method.ResetBody(); //HACK!!!
       
+      ProcessCustomAttributes(method.GetModifiers().GetCustomAttributes());
+      
       def pExpr = method.BodyParsed;
 
       when (pExpr != null)
@@ -285,9 +288,7 @@
         });
       }
 
-      // Get the method region location.
-      //
-      AddRegion(method.Location.TrimStart(method.Header.ret_type_loc, false), true);
+      AddRegion(method.Location.TrimStart(method.Header.Location, false), true);
     }
 
     ProcessProperty(prop : PropertyBuilder) : void
@@ -328,6 +329,39 @@
 
     mutable _start : int;
 
+    ProcessCustomAttributes(attrs : list[PExpr]) : void
+    {
+      def combineLocations(attrs) : Location
+      {
+        match(attrs)
+        {
+        | x :: xs => 
+            if(x.Location.FileIndex == _fileIndex)
+              x.Location.Combine(combineLocations(xs)); 
+            else
+              combineLocations(xs);
+        | _ => Location.Default;
+        }
+      }
+      
+      match(attrs)
+      {
+      | _ :: _ => 
+          def combined = combineLocations(attrs);
+          
+          _addHiddenRegion(
+            Location(combined.FileIndex,  // expand a combined location a little to include 
+                     combined.Line,       // opening and closing square brackets.
+                     combined.Column - 1,
+                     combined.EndLine,
+                     combined.EndColumn + 1), 
+            "[custom attributes]", 
+            false);
+      | _ => ();
+      }
+      
+    }
+
     ProcessBuilder(builder : TypeBuilder) : void
     {
       //VladD2: VariantOption может содержать в себе другие члены.
@@ -336,6 +370,8 @@
 
       foreach (part when part.Location.FileIndex == _fileIndex in builder.AstParts)
       {
+        ProcessCustomAttributes(part.GetCustomAttributes());
+        
         _addHiddenRegion(
           Location(
             _fileIndex,

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	Mon Apr  2 21:07:58 2007
@@ -1,5 +1,7 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
 
 using Nemerle.Collections;
 using Nemerle.Compiler;
@@ -740,6 +742,9 @@
       when (resetQuotationStart && !_tokenInfo.IsWhiteSpaceOrCommentType)
         _tokenInfo.State &= ~ScanState.QuotationStart;
 
+      when(_tokenInfo.IsCommentType)
+        CheckForSpecialComments(_tokenInfo);
+
       when (_tokenInfo.IsQuotation && !(_tokenInfo.Token is Token.BeginQuote))
       {
         _tokenInfo.Color = match (_tokenInfo.Color)
@@ -770,6 +775,41 @@
                  //phantom: 2VladD2: они просто маленькие... когда они вырастут, станут различаться. :)
     }
     
+    #region Support for special comments
+    static specialCommentRegexes : list[ScanTokenColor * Regex] = 
+      [
+        (ScanTokenColor.CommentTODO, Regex(@"\b(TODO)\b\s*:", RegexOptions.Compiled)),
+        (ScanTokenColor.CommentBUG, Regex(@"\b(BUG)\b\s*:", RegexOptions.Compiled)),
+        (ScanTokenColor.CommentHACK, Regex(@"\b(HACK)\b\s*:", RegexOptions.Compiled))
+      ];
+    
+    CheckForSpecialComments(tokenInfo : ScanTokenInfo) : void
+    { 
+      def chooseColor(str, regexList)
+      {
+        match(regexList)
+        {
+        | (color, regex) :: xs => 
+                if(regex.Match(str).Success)
+                  (true, color)
+                else
+                  chooseColor(str, xs)
+        | _ => (false, ScanTokenColor.Comment) // this color will be ignored.
+        }
+      }
+      
+      match(tokenInfo.Token)
+      {
+      | Comment(value) =>
+            //Debug.WriteLine($"Comment value: $value");
+            def (success, color) = chooseColor(value.Substring(2), specialCommentRegexes);
+            when(success)
+              tokenInfo.Color = color;
+      | _ => () 
+      }
+    }
+    #endregion
+    
     checkForHighlights(tokenInfo : ScanTokenInfo) : bool
     {
       mutable highlighted = true;

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanTokenColor.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanTokenColor.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/ScanTokenColor.n	Mon Apr  2 21:07:58 2007
@@ -44,5 +44,10 @@
   
   | HighlightOne
   | HighlightTwo
+
+  // KLiss: Special kinds of comments deserve special coloring. :-)
+  | CommentTODO
+  | CommentBUG
+  | CommentHACK
   }
 }

Modified: vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/TokenFinder.n
==============================================================================
--- vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/TokenFinder.n	(original)
+++ vs-plugin/trunk/Nemerle.Compiler.Utils/Nemerle.Completion2/CodeModel/TokenFinder.n	Mon Apr  2 21:07:58 2007
@@ -60,6 +60,52 @@
       if (_stop) (newStack) else (stack);
     }
 
+    Go(token : Token, predicate : Token -> bool, stack : list[Token]) : list[Token]
+    {
+      when (_stop || token == null)
+        return stack;
+
+      Print(token, token.Location, _counter);
+      _counter++;
+
+      mutable newStack = match (token)
+      {
+      | RoundGroup (child)    // {         Child : Token; } // ( ... )
+      | BracesGroup(child)    // {         Child : Token; } // { ... }
+      | SquareGroup(child)    // { mutable Child : Token; } // [ ... ]
+      | QuoteGroup (child)    // {         Child : Token; } // <[ ... ]>
+      | LooseGroup (child)    // { mutable Child : Token; } // ; ... ;
+      | Namespace(_,child) => // { Env : GlobalEnv; Body : Token; }
+
+        if (_stop)
+          stack
+        else
+        {
+          _stop = predicate(token) && IsAfter(token.Location);
+
+          if (_stop)
+            token :: stack
+          else
+            Go(child, predicate, token :: stack);
+        }
+      | _ => stack
+
+      }
+
+      _counter--;
+
+      unless (_stop)
+      {
+        _stop = predicate(token) && IsAfter(token.Location);
+
+        unless (_stop)
+          newStack = Go(token.Next, predicate, newStack);
+      }
+
+      if (_stop) (newStack) else (stack);
+    }
+    
+
     public Find(
       root : Token,
       line : int,
@@ -72,6 +118,20 @@
       Go(root, [])
     }
 
+    public FindAfter(
+      root : Token,
+      line : int,
+      col  : int,
+      predicate : Token -> bool
+    )
+      : list[Token]
+    {
+      Init(root.Location, line, col);
+
+      Go(root, predicate, [])
+    }
+    
+
     #endregion
 
     #region Helpers
@@ -102,6 +162,18 @@
       location.Contains(_line, _col);
     }
 
+    IsAfter(location : Location) : bool
+    {
+      if(location.Line > _line)
+        true;
+      else if(location.Line < _line)
+        false;
+      else if(location.Column > _col)
+        true;
+      else 
+        false;
+    }
+
     Print(obj : object, loc : Location, level : int) : void
     {
 #if PRINT_AST && DEBUG

Modified: vs-plugin/trunk/Nemerle.VsIntegration/CtcComponents/PkgCmd.ctc
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/CtcComponents/PkgCmd.ctc	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/CtcComponents/PkgCmd.ctc	Mon Apr  2 21:07:58 2007
@@ -64,7 +64,7 @@
     
     // Menu's ID                                        Parent                                 Priority   Type      Name          Text
 //phantom: if you want the menu back, uncomment
-    //guidNemerleProjectCmdSet:NemerleTopLevelMenu, guidNemerleProjectCmdSet:VsTopLevelMenuGroup,  0x000,   ,  "NemerleMenu",      "&Nemerle" ;
+    guidNemerleProjectCmdSet:NemerleTopLevelMenu, guidNemerleProjectCmdSet:VsTopLevelMenuGroup,  0x000,   ,  "NemerleMenu",      "&Nemerle" ;
     guidNemerleProjectCmdSet:Selection,           guidNemerleProjectCmdSet:NemerleGroup,         0x000,   ,  "NemerleSelection", "&Selection" ;
     guidNemerleProjectCmdSet:Refactor,            guidNemerleProjectCmdSet:NemerleGroup,         0x000,   ,  "NemerleRefactor",  "&Refactor" ;
     guidNemerleProjectCmdSet:Highlighting,        guidNemerleProjectCmdSet:NemerleGroup,         0x000,   ,  "NemerleHighlighting",  "&Highlighting" ;
@@ -191,5 +191,6 @@
   //phantom: try to play with it only after menu will be fixed (handlers leashing)
   guidNemerleProjectCmdSet:cmdIdExtendSelection,   guidNemerleEditorFactory,   guidNemerleEditorFactory,        'W':C;
   guidNemerleProjectCmdSet:cmdIdShrinkSelection,   guidNemerleEditorFactory,   guidNemerleEditorFactory,        'W':CS;
+  guidNemerleProjectCmdSet:cmdIdAddHighlighting,   guidNemerleEditorFactory,   guidNemerleEditorFactory,        0x76:CS;  // This doesn't work?
 
 KEYBINDINGS_END

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorableItem.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorableItem.cs	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorableItem.cs	Mon Apr  2 21:07:58 2007
@@ -47,12 +47,24 @@
 
 		public NemerleColorableItem(
 			string displayName, COLORINDEX foreColor, COLORINDEX backColor, Color hiForeColor, Color hiBackColor)
+			: this(
+				"Nemerle - " + displayName,
+				foreColor,   
+                backColor,
+				hiForeColor, 
+                hiBackColor,
+				FONTFLAGS.FF_DEFAULT)
+		{
+		}
+		public NemerleColorableItem(
+			string displayName, COLORINDEX foreColor, COLORINDEX backColor, Color hiForeColor, Color hiBackColor,
+            FONTFLAGS fontFlags)
 			: base(
 				"Nemerle - " + displayName,
 				"Nemerle - " + displayName,
 				foreColor,   backColor,
 				hiForeColor, hiBackColor,
-				FONTFLAGS.FF_DEFAULT)
+				fontFlags)
 		{
 		}
 	}

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorizer.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorizer.cs	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleColorizer.cs	Mon Apr  2 21:07:58 2007
@@ -15,7 +15,6 @@
 		public override int ColorizeLine(int line, int length, IntPtr ptr, int state, uint[] attrs)
 		{
 			NemerleScanner scanner = (NemerleScanner)Scanner;
-
 			scanner._currentLine = line;
 
 			int ret;

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	Mon Apr  2 21:07:58 2007
@@ -832,6 +832,11 @@
 
 			new NemerleColorableItem("Highlight One", COLORINDEX.CI_BLACK, COLORINDEX.CI_YELLOW, Color.Empty, Color.FromArgb(255, 255, 200)),
 			new NemerleColorableItem("Highlight Two", COLORINDEX.CI_BLACK, COLORINDEX.CI_GREEN, Color.Empty, Color.FromArgb(230, 255, 230)),
+
+            new NemerleColorableItem("TODO comment", COLORINDEX.CI_BLUE, COLORINDEX.CI_WHITE, Color.Empty, Color.Empty),
+			new NemerleColorableItem("BUG comment", COLORINDEX.CI_RED, COLORINDEX.CI_WHITE, Color.Empty, Color.Empty, FONTFLAGS.FF_BOLD),
+			new NemerleColorableItem("HACK comment", COLORINDEX.CI_RED, COLORINDEX.CI_WHITE, Color.Empty, Color.Empty)
+
 		};
 
 		Dictionary<IVsTextLines, NemerleColorizer> _colorizers = new Dictionary<IVsTextLines,NemerleColorizer>();

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  2 21:07:58 2007
@@ -5,7 +5,7 @@
 using Microsoft.VisualStudio;
 using Microsoft.VisualStudio.Package;
 using Microsoft.VisualStudio.TextManager.Interop;
-
+using Nemerle.Completion2.CodeFormatting;
 using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
 
 using Nemerle.Completion2;
@@ -172,9 +172,15 @@
 			ProjectInfo projectInfo = ProjectInfo.FindProject(filePath);
 			Engine engine = projectInfo.Engine;
 
-			Formatter f = new Formatter(engine);
-			List<FormatterResult> results = f.FormatDocument(filePath);
-
+            ReformatSpan_internal(mgr, span, engine, filePath);
+            ReformatSpan_internal(mgr, span, engine, filePath);
+            ReformatSpan_internal(mgr, span, engine, filePath);
+            //base.ReformatSpan(mgr, span);
+		}
+        private void ReformatSpan_internal(EditArray _mgr, TextSpan span, Engine engine, string filePath)
+        {
+            List<FormatterResult> results = Formatter.FormatDocument(engine, filePath);
+            EditArray mgr = new EditArray(_mgr.Source, _mgr.TextView, true, "formatting");
 			foreach (FormatterResult res in results)
 			{ 
 				TextSpan loc = new TextSpan();
@@ -186,7 +192,6 @@
 				mgr.Add(new EditSpan(loc, res.ReplacementString));
 			}
 			mgr.ApplyEdits();
-			//base.ReformatSpan(mgr, span);
 		}
 
 		private MethodData _methodData;

Modified: vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleViewFilter.cs
==============================================================================
--- vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleViewFilter.cs	(original)
+++ vs-plugin/trunk/Nemerle.VsIntegration/LanguageService/NemerleViewFilter.cs	Mon Apr  2 21:07:58 2007
@@ -150,6 +150,7 @@
 																					 true);
 			}
 		}
+
 		private void RemoveLastHighlighting()
 		{
 			NemerleSource source = Source as NemerleSource;



More information about the svn mailing list