]> O.S.I.I.S - jp/crowedit.git/commitdiff
source structure and code clean
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 3 Jul 2025 17:52:58 +0000 (19:52 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 3 Jul 2025 17:52:58 +0000 (19:52 +0200)
14 files changed:
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/Compiler/SyntaxNode.cs [deleted file]
CrowEditBase/src/Compiler/SyntaxNodes/MultiNodeSyntax.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/SyntaxNodes/SingleTokenSyntax.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/SyntaxNodes/SyntaxNode.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/SyntaxNodes/SyntaxRootNode.cs [new file with mode: 0644]
CrowEditBase/src/Compiler/SyntaxRootNode.cs [deleted file]
CrowEditBase/src/Document.cs
CrowEditBase/src/TextDocument.cs
plugins/CERoslynPlugin/src/CSSyntaxAnalyser.cs [deleted file]
plugins/CERoslynPlugin/src/Parsing/CSSyntaxAnalyser.cs [new file with mode: 0644]
plugins/CERoslynPlugin/src/Parsing/CsharpSyntaxWalkerBridge.cs [new file with mode: 0644]
plugins/CERoslynPlugin/src/Parsing/SyntaxNodes.cs [new file with mode: 0644]
plugins/CEXmlPlugin/src/Parsing/XmlSyntaxNodes.cs

index 5db2e43e99ca332411ede2f80e0eeeda9d306055..1c5f98f60a1ca6ba8d90c3b56636187338599643 100644 (file)
@@ -16,35 +16,49 @@ using System.Threading.Tasks;
 namespace CrowEditBase
 {
        public abstract class SourceDocument : TextDocument {
+               #region CTOR
                public SourceDocument (string fullPath, string editorPath = "#ui.sourceEditor.itmp")
                        : base (fullPath, editorPath) {
                }
+               #endregion
+
                protected SyntaxRootNode root;
+               CancellationTokenSource cancelSource;
+               Task backgroundCompilationTask;
 
+        public SyntaxRootNode Root {
+                       get => root;
+               }
+               public bool IsParsed => root != null && Tokens.Length > 0;
+               public ReadOnlySpan<Token> Tokens => root.Tokens;
+               public IEnumerable<SyntaxNode> SyntaxRootChildNodes => root?.children;
+               public SyntaxException CurrentException {
+                       get => CrowEditBase.App.CurrentException;
+                       set {
+                               CrowEditBase.App.CurrentException = value;
+                               SetLocation(value.Location);
+                       } 
+               }
+               
+               #region commands
                public Command CMDRefreshSyntaxTree;
-
         protected override void initCommands()
         {
             base.initCommands();
 
                        CMDRefreshSyntaxTree = new ActionCommand ("Reparse", parse, "#icons.refresh.svg", true);
         }
-        public SyntaxRootNode Root {
-                       get => root;
-               }
-
-               public bool IsParsed => root != null && Tokens.Length > 0;
-               public ReadOnlySpan<Token> Tokens => root.Tokens;
-               public IEnumerable<SyntaxNode> SyntaxRootChildNodes => root?.children;
+               #endregion
 
+               #region token & node searching
+               public Token GetTokenByIndex(int tokIdx) => IsParsed && tokIdx >= 0 ?
+                                               Tokens[Math.Min(Tokens.Length - 1, tokIdx)] : default;
                public Token FindTokenIncludingPosition (int pos) {
                        if (!IsParsed || pos == 0 || Tokens.Length == 0)
                                return default;
                        int idx = Tokens.BinarySearch(new  Token (pos));
                        return idx == 0 ? Tokens[0] : idx < 0 ? Tokens[~idx - 1] : Tokens[idx];
                }
-               public Token GetTokenByIndex(int tokIdx) => IsParsed && tokIdx >= 0 ?
-                                               Tokens[Math.Min(Tokens.Length - 1, tokIdx)] : default;
                public int FindTokenIndexIncludingPosition (int pos) {
                        if (!IsParsed || pos == 0 || Tokens.Length == 0)
                                return default;
@@ -55,6 +69,7 @@ namespace CrowEditBase
                /// if outermost is true, return oldest ancestor exept root node, useful for folding.
                /// </summary>
                public SyntaxNode FindNodeIncludingPosition (int pos, bool outerMost = false) {
+
                        if (root == null)
                                return null;
                        if (!root.Contains (pos))
@@ -66,21 +81,9 @@ namespace CrowEditBase
                        }
                        return sn;
                }
-               /*public T FindNodeIncludingPosition<T> (int pos) {
-                       if (root == null)
-                               return default;
-                       if (!root.Contains (pos))
-                               return default;
-                       return root.FindNodeIncludingPosition<T> (pos);
-               }
-               public SyntaxNode FindNodeIncludingSpan (TextSpan span) {
-                       if (root == null)
-                               return null;
-                       if (!root.Contains (span))
-                               return null;
-                       return root.FindNodeIncludingSpan (span);
-               }*/
+               #endregion
                
+               #region TextDocument implementation
                protected override void reloadFromFile () {
                        base.reloadFromFile ();
                        parse ();
@@ -124,7 +127,7 @@ namespace CrowEditBase
 
                        //Console.WriteLine ($"CurrentToken: idx({currentTokenIndex}) {currentToken} {RootNode.Root.GetTokenStringByIndex(currentTokenIndex)}");
                }
-
+               #endregion
 
                public virtual Color GetColorForToken (Token token)
                {
@@ -143,8 +146,6 @@ namespace CrowEditBase
                //protected abstract Tokenizer CreateTokenizer ();
                protected abstract SyntaxAnalyser CreateSyntaxAnalyser ();
                public abstract IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode currentNode, CharLocation loc);
-               CancellationTokenSource cancelSource;
-               Task backgroundCompilationTask;
                protected virtual async void parse () {
                        if (backgroundCompilationTask != null && !backgroundCompilationTask.IsCompleted) {
                                cancelSource.Cancel();
@@ -170,13 +171,6 @@ namespace CrowEditBase
                        NotifyValueChanged ("SyntaxRootChildNodes", SyntaxRootChildNodes);
                }
 
-               public SyntaxException CurrentException {
-                       get => CrowEditBase.App.CurrentException;
-                       set {
-                               CrowEditBase.App.CurrentException = value;
-                               SetLocation(value.Location);
-                       } 
-               }
 
        }
 }
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxNode.cs b/CrowEditBase/src/Compiler/SyntaxNode.cs
deleted file mode 100644 (file)
index ed777ea..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Crow.Text;
-using Crow;
-using System.Diagnostics;
-
-namespace CrowEditBase
-{
-       public class UnexpectedTokenSyntax : SingleTokenSyntax {
-               public UnexpectedTokenSyntax(Token tok) : base (tok) { }
-       }
-       public class SingleTokenSyntax : SyntaxNode {
-               protected Token token;
-        public override TokenType Type => token.Type;
-        public override int SpanStart => token.Start;
-               public override int SpanEnd => token.End;
-        public override bool IsComplete => token.Type != TokenType.Unknown && token.Length > 0;
-        public SingleTokenSyntax(Token tok) {
-                       token = tok;
-                       token.syntaxNode = this;
-               }
-       }
-       public class CommentTriviaSyntax : MultiNodeSyntax {
-               bool block;
-               public CommentTriviaSyntax(bool block) {
-                       this.block = block;
-               }
-        public override bool IsComplete => true;
-                       
-    }
-       public abstract class MultiNodeSyntax : SyntaxNode {
-               public MultiNodeSyntax() { }
-        internal List<SyntaxNode> children = new List<SyntaxNode> ();
-               public IEnumerable<SyntaxNode> Children => children;
-               public SyntaxNode AddChild (SyntaxNode child) {
-                       children.Add (child);
-                       child.Parent = this;
-                       return child;
-               }
-               public void RemoveChild (SyntaxNode child) {
-                       children.Remove (child);
-                       child.Parent = null;
-               }
-               public IEnumerable<T> GetChilds<T> () => children.OfType<T>();
-
-               public bool ChildIs<T> (int idx) => children.Count() <= idx ? false : children[idx] is T;
-               public bool ChildSequenceIs(params object[] sequ) {
-                       if (children.Count != sequ.Length)
-                               return false;
-                       for (int i = 0; i < sequ.Length; i++) {
-                               if (typeof(Type).IsAssignableFrom(sequ[i].GetType())) {
-                                       if ((sequ[i] as Type) != children[i].GetType())
-                                               return false;
-                               } else if (sequ[i].GetType().IsEnum) {
-                                       if (!(children[i] is SingleTokenSyntax tok) || (TokenType)sequ[i] != tok.Type)
-                                               return false;
-                               } else
-                                       return false;
-                               if (!children[i].IsComplete)
-                                       return false;
-                               
-                       }
-                       return true;
-               }
-        public override bool IsComplete {
-                       get {
-                               for (int i = 0; i < children.Count(); i++) {
-                                       if (!children[i].IsComplete)
-                                               return false;
-                               }
-                               return true;
-                       }
-               }
-        public override bool HasChilds => children.Count > 0;
-        public override int SpanStart => HasChilds ? children[0].SpanStart : 0;
-               public override int SpanEnd => HasChilds ? children[children.Count - 1].SpanEnd : 0;
-               /*public override int SpanEnd {//to be removed, used for debugging
-                       get {
-                               if (HasChilds) {
-                                       
-                                       if (children[children.Count - 1] == this)
-                                               System.Diagnostics.Debugger.Break();
-                                       return children[children.Count - 1].SpanEnd;
-                               } else return 0;                                
-                       }
-               } */
-
-               internal bool isFolded;
-               public virtual bool IsFoldable => IsComplete && !(Parent != Root && Parent.StartLocation.Line == StartLocation.Line) && LineCount > 1;
-               public void ExpandToTheTop () {
-                       isExpanded = true;
-                       Parent?.ExpandToTheTop ();
-               }
-               public virtual void UnfoldToTheTop () {
-                       isFolded = false;
-                       Parent.UnfoldToTheTop ();
-               }
-               public IEnumerable<MultiNodeSyntax> VisibleFoldableNodes {
-                       get {
-                               if (IsFoldable) {
-                                       yield return this;
-                               }
-                               if (!isFolded) {
-                                       foreach (MultiNodeSyntax n in Children.OfType<MultiNodeSyntax>()) {
-                                               foreach (MultiNodeSyntax folds in n.VisibleFoldableNodes)
-                                                       yield return folds;
-                                       }
-                               }
-                       }
-               }
-               
-               public virtual int FoldedLineCount {
-                       get {
-                               if (isFolded)
-                                       return LineCount;
-                               int tmp = 0;
-                               if (HasChilds) {
-                                       foreach (MultiNodeSyntax n in children.OfType<MultiNodeSyntax>().Where (c => c.IsFoldable))
-                                               tmp += n.FoldedLineCount;
-                               }
-                               return tmp;
-                       }
-               }
-               public override SyntaxNode FindNodeIncludingSpan (TextSpan span) {
-                       foreach (SyntaxNode node in children) {
-                               if (node.Contains (span))
-                                       return node.FindNodeIncludingSpan (span);
-                       }
-                       return this;
-               }
-               public override SyntaxNode FindNodeIncludingPosition (int pos) {
-                       foreach (SyntaxNode node in children) {
-                               if (node.Contains (pos))
-                                       return node.FindNodeIncludingPosition (pos);
-                       }
-                       return this;
-               }
-               bool _isExpanded;
-               public override bool isExpanded {
-                       get => _isExpanded;
-                       set {
-                               bool expand = HasChilds ? value : false;
-                               if  (_isExpanded == expand)
-                                       return;
-                               _isExpanded = value;
-                               if (isExpanded && Parent is SyntaxNode sn) {
-                                       try {
-                                               sn.isExpanded = true;
-                                       } catch (Exception ex) {
-                                               Debug.WriteLine($"SyntaxNode expand to the top failed:{ex.Message}");
-                                               Debug.WriteLine(ex.StackTrace);
-                                       }
-                                       
-                               }
-                               NotifyValueChanged (_isExpanded);
-                       }
-               }               
-    }
-       public abstract class SyntaxNode : CrowEditComponent {
-
-
-               #region  Folding and ?expand?
-               public virtual bool isExpanded {
-                       get => false;
-                       set {
-                               if (value && Parent is SyntaxNode sn) {
-                                       sn.isExpanded = true;                                   
-                               }
-                       }
-               }
-               #endregion
-               public MultiNodeSyntax Parent { get; internal set; }
-               public virtual SyntaxRootNode Root => Parent.Root;
-               public virtual TokenType Type => TokenType.Unknown;
-               public virtual int SpanStart => 0;
-               public virtual int SpanEnd => 0;
-
-               
-               public virtual bool HasChilds => false;
-               public virtual bool IsComplete => false;
-
-
-
-               /*public int StartLine { get; private set; }
-               public virtual int LineCount => lineCount;*/
-
-
-               /*List<SyntaxException> exceptions = new List<SyntaxException>();
-               public IEnumerable<SyntaxException> Exceptions => exceptions;
-               public void AddException(SyntaxException e) => exceptions.Add(e);
-               public void ResetExceptions(SyntaxException e) => exceptions.Clear();
-               public IEnumerable<SyntaxException> GetAllExceptions() {
-                               foreach (SyntaxException e in exceptions)
-                                       yield return e;
-                               foreach (SyntaxNode n in Children) {
-                                       foreach (SyntaxException ce in n.GetAllExceptions())
-                                               yield return ce;
-                               }
-               }*/
-
-
-               protected Token getTokenByIndex (int idx) => Root.GetTokenByIndex(idx);
-
-               
-               //public int IndexOf (SyntaxNode node) => children.IndexOf (node);
-               public SyntaxNode NextSibling {
-                       get {
-                               if (Parent != null) {
-                                       int idx  = Parent.children.IndexOf (this);
-                                       if (idx < Parent.children.Count - 1)
-                                               return Parent.children[idx + 1];
-                               }
-                               return null;
-                       }
-               }
-               public SyntaxNode PreviousSibling {
-                       get {
-                               if (Parent != null) {
-                                       int idx  = Parent.children.IndexOf (this);
-                                       if (idx > 0)
-                                               return Parent.children[idx - 1];
-                               }
-                               return null;
-                       }
-               }
-               public virtual SyntaxNode NextSiblingOrParentsNextSibling
-                       => NextSibling ?? Parent.NextSiblingOrParentsNextSibling;
-
-               /*public virtual int TokenIndexBase { get; private set; }
-               public virtual int TokenCount => lastTokenOfset.HasValue ? lastTokenOfset.Value + 1 : 0;
-               public int? LastTokenIndex =>  lastTokenOfset.HasValue ? TokenIndexBase + lastTokenOfset.Value : null;
-
-               public int EndLine {
-                       set {
-                               lineCount = value - StartLine + 1;
-                       }
-                       get => StartLine + lineCount - 1;
-               }*/
-               public TextSpan Span => new TextSpan (SpanStart, SpanEnd);
-               public CharLocation StartLocation => Root.GetLocation(SpanStart);
-               public CharLocation EndLocation => Root.GetLocation(SpanEnd);
-               public int LineCount => EndLocation.Line - StartLocation.Line + 1;
-
-               /*
-               public void Replace (SyntaxNode newNode) {
-                       Parent.replaceChild (this, newNode);
-               }
-               void replaceChild (SyntaxNode oldNode, SyntaxNode newNode) {
-                       int idx = children.IndexOf (oldNode);
-                       children[idx] = newNode;
-                       newNode.Parent = this;
-                       int tokIdxDiff = newNode.TokenCount - oldNode.TokenCount;
-                       int lineDiff = newNode.EndLine - oldNode.EndLine;
-                       if (tokIdxDiff == 0 && lineDiff == 0)
-                               return;
-
-                       SyntaxNode curNode = this;
-                       while (curNode != null) {
-                               curNode.lineCount += lineDiff;
-                               curNode.TokenCount += tokIdxDiff;
-                               if (curNode is SyntaxRootNode)
-                                       break;
-                               while (++idx < curNode.children.Count)
-                                       curNode.children[idx].offset (tokIdxDiff, lineDiff);
-                               idx = curNode.Parent.children.IndexOf (curNode);
-                               curNode = curNode.Parent;
-                       }
-               }*/
-               /*void offset (int tokenOffset, int lineOffset) {
-                       TokenIndexBase += tokenOffset;
-                       StartLine += lineOffset;
-                       foreach (SyntaxNode child in children) {
-                               child.offset (tokenOffset, lineOffset);
-                       }
-               }*/
-/*             
-               public T FindNodeIncludingPosition<T> (int pos) {
-                       foreach (SyntaxNode node in children) {
-                               if (node.Contains (pos))
-                                       return node.FindNodeIncludingPosition<T> (pos);
-                       }
-
-                       return this is T tt ? tt : default;
-               }*/
-               public virtual SyntaxNode FindNodeIncludingPosition (int pos) => this;
-               public virtual SyntaxNode FindNodeIncludingSpan (TextSpan span) => this;
-               
-               public bool Contains (int pos) => Span.Contains (pos);
-               public bool Contains (TextSpan span) => Span.Contains (span);
-               /*public void Dump (int level = 0) {
-                       Console.WriteLine ($"{new string('\t', level)}{this}");
-                       foreach (SyntaxNode node in children)
-                               node.Dump (level + 1);
-               }*/
-               //public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{TokenCount} {this.GetType().Name}";
-               public override string ToString() => $"{this.GetType().Name}";
-               public string AsText() {
-                       return Span.Length < 0 ? "" : Root.GetText(Span).ToString();
-               }
-               public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
-
-
-        public class CompareOnStartLine : IComparer<SyntaxNode>
-        {
-            public int Compare(SyntaxNode x, SyntaxNode y) => x.StartLocation.Line - y.StartLocation.Line;
-        }
-    }
-}
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxNodes/MultiNodeSyntax.cs b/CrowEditBase/src/Compiler/SyntaxNodes/MultiNodeSyntax.cs
new file mode 100644 (file)
index 0000000..5081019
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Crow.Text;
+using Crow;
+using System.Diagnostics;
+
+namespace CrowEditBase
+{
+       public abstract class MultiNodeSyntax : SyntaxNode {
+               #region CTOR
+               public MultiNodeSyntax() { }
+               #endregion
+
+               internal bool isFolded;
+               bool _isExpanded;
+
+        internal List<SyntaxNode> children = new List<SyntaxNode> ();
+               public IEnumerable<SyntaxNode> Children => children;
+               public SyntaxNode AddChild (SyntaxNode child) {
+                       children.Add (child);
+                       child.Parent = this;
+                       return child;
+               }
+               public void RemoveChild (SyntaxNode child) {
+                       children.Remove (child);
+                       child.Parent = null;
+               }
+               public IEnumerable<T> GetChilds<T> () => children.OfType<T>();
+
+               public bool ChildIs<T> (int idx) => children.Count() <= idx ? false : children[idx] is T;
+               public bool ChildSequenceIs(params object[] sequ) {
+                       if (children.Count != sequ.Length)
+                               return false;
+                       for (int i = 0; i < sequ.Length; i++) {
+                               if (typeof(Type).IsAssignableFrom(sequ[i].GetType())) {
+                                       if ((sequ[i] as Type) != children[i].GetType())
+                                               return false;
+                               } else if (sequ[i].GetType().IsEnum) {
+                                       if (!(children[i] is SingleTokenSyntax tok) || (TokenType)sequ[i] != tok.Type)
+                                               return false;
+                               } else
+                                       return false;
+                               if (!children[i].IsComplete)
+                                       return false;
+                               
+                       }
+                       return true;
+               }
+        
+               #region SyntaxNode implementation
+               public override bool isExpanded {
+                       get => _isExpanded;
+                       set {
+                               bool expand = HasChilds ? value : false;
+                               if  (_isExpanded == expand)
+                                       return;
+                               _isExpanded = value;
+                               if (isExpanded && Parent is SyntaxNode sn) {
+                                       try {
+                                               sn.isExpanded = true;
+                                       } catch (Exception ex) {
+                                               Debug.WriteLine($"SyntaxNode expand to the top failed:{ex.Message}");
+                                               Debug.WriteLine(ex.StackTrace);
+                                       }
+                                       
+                               }
+                               NotifyValueChanged (_isExpanded);
+                       }
+               }               
+               public override bool IsComplete {
+                       get {
+                               for (int i = 0; i < children.Count(); i++) {
+                                       if (!children[i].IsComplete)
+                                               return false;
+                               }
+                               return true;
+                       }
+               }
+        public override bool HasChilds => children.Count > 0;
+        public override int SpanStart => HasChilds ? children[0].SpanStart : 0;
+               public override int SpanEnd => HasChilds ? children[children.Count - 1].SpanEnd : 0;
+               public override SyntaxNode FindNodeIncludingSpan (TextSpan span) {
+                       foreach (SyntaxNode node in children) {
+                               if (node.Contains (span))
+                                       return node.FindNodeIncludingSpan (span);
+                       }
+                       return this;
+               }
+               public override SyntaxNode FindNodeIncludingPosition (int pos) {
+                       foreach (SyntaxNode node in children) {
+                               if (node.Contains (pos))
+                                       return node.FindNodeIncludingPosition (pos);
+                       }
+                       return this;
+               }
+               #endregion
+
+               public virtual bool IsFoldable => IsComplete && !(Parent != Root && Parent.StartLocation.Line == StartLocation.Line) && LineCount > 1;
+               public virtual void UnfoldToTheTop () {
+                       isFolded = false;
+                       Parent.UnfoldToTheTop ();
+               }
+               public virtual int FoldedLineCount {
+                       get {
+                               if (isFolded)
+                                       return LineCount;
+                               int tmp = 0;
+                               if (HasChilds) {
+                                       foreach (MultiNodeSyntax n in children.OfType<MultiNodeSyntax>().Where (c => c.IsFoldable))
+                                               tmp += n.FoldedLineCount;
+                               }
+                               return tmp;
+                       }
+               }
+               
+               public void ExpandToTheTop () {
+                       isExpanded = true;
+                       Parent?.ExpandToTheTop ();
+               }
+               public IEnumerable<MultiNodeSyntax> VisibleFoldableNodes {
+                       get {
+                               if (IsFoldable) {
+                                       yield return this;
+                               }
+                               if (!isFolded) {
+                                       foreach (MultiNodeSyntax n in Children.OfType<MultiNodeSyntax>()) {
+                                               foreach (MultiNodeSyntax folds in n.VisibleFoldableNodes)
+                                                       yield return folds;
+                                       }
+                               }
+                       }
+               }
+               
+   }
+}
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxNodes/SingleTokenSyntax.cs b/CrowEditBase/src/Compiler/SyntaxNodes/SingleTokenSyntax.cs
new file mode 100644 (file)
index 0000000..3253e9f
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace CrowEditBase
+{
+       public class SingleTokenSyntax : SyntaxNode {
+               #region CTOR
+        public SingleTokenSyntax(Token tok) {
+                       token = tok;
+                       token.syntaxNode = this;
+               }
+               #endregion
+
+               protected Token token;
+
+               #region SyntaxNode implementation
+        public override TokenType Type => token.Type;
+        public override int SpanStart => token.Start;
+               public override int SpanEnd => token.End;
+        public override bool IsComplete => token.Type != TokenType.Unknown && token.Length > 0;
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxNodes/SyntaxNode.cs b/CrowEditBase/src/Compiler/SyntaxNodes/SyntaxNode.cs
new file mode 100644 (file)
index 0000000..092d54b
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Collections.Generic;
+using Crow.Text;
+
+namespace CrowEditBase
+{
+       public class UnexpectedTokenSyntax : SingleTokenSyntax {
+               public UnexpectedTokenSyntax(Token tok) : base (tok) { }
+       }
+       public class CommentTriviaSyntax : MultiNodeSyntax {
+               bool block;
+               public CommentTriviaSyntax(bool block) {
+                       this.block = block;
+               }
+        public override bool IsComplete => true;
+                       
+    }
+       
+       public abstract class SyntaxNode : CrowEditComponent {
+
+               public MultiNodeSyntax Parent { get; internal set; }
+
+               #region  Folding and ?expand?
+               public virtual bool isExpanded {
+                       get => false;
+                       set {
+                               if (value && Parent is SyntaxNode sn) {
+                                       sn.isExpanded = true;                                   
+                               }
+                       }
+               }
+               #endregion
+               
+               public virtual SyntaxRootNode Root => Parent.Root;
+               public virtual TokenType Type => TokenType.Unknown;
+               public virtual int SpanStart => 0;
+               public virtual int SpanEnd => 0;
+               public virtual bool HasChilds => false;
+               public virtual bool IsComplete => false;
+               public virtual SyntaxNode FindNodeIncludingPosition (int pos) => this;
+               public virtual SyntaxNode FindNodeIncludingSpan (TextSpan span) => this;
+               public virtual SyntaxNode NextSiblingOrParentsNextSibling
+                       => NextSibling ?? Parent.NextSiblingOrParentsNextSibling;
+
+
+               public SyntaxNode NextSibling {
+                       get {
+                               if (Parent != null) {
+                                       int idx  = Parent.children.IndexOf (this);
+                                       if (idx < Parent.children.Count - 1)
+                                               return Parent.children[idx + 1];
+                               }
+                               return null;
+                       }
+               }
+               public SyntaxNode PreviousSibling {
+                       get {
+                               if (Parent != null) {
+                                       int idx  = Parent.children.IndexOf (this);
+                                       if (idx > 0)
+                                               return Parent.children[idx - 1];
+                               }
+                               return null;
+                       }
+               }
+
+               protected Token getTokenByIndex (int idx) => Root.GetTokenByIndex(idx);
+
+
+               public TextSpan Span => new TextSpan (SpanStart, SpanEnd);
+               public CharLocation StartLocation => Root.GetLocation(SpanStart);
+               public CharLocation EndLocation => Root.GetLocation(SpanEnd);
+               public int LineCount => EndLocation.Line - StartLocation.Line + 1;
+
+               public bool Contains (int pos) => Span.Contains (pos);
+               public bool Contains (TextSpan span) => Span.Contains (span);
+               public string AsText() {
+                       return Span.Length < 0 ? "" : Root.GetText(Span).ToString();
+               }
+               public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
+
+        public class CompareOnStartLine : IComparer<SyntaxNode>
+        {
+            public int Compare(SyntaxNode x, SyntaxNode y) => x.StartLocation.Line - y.StartLocation.Line;
+        }
+               public override string ToString() => $"{this.GetType().Name}";
+
+               #region to clean
+               /*public int StartLine { get; private set; }
+               public virtual int LineCount => lineCount;*/
+
+               /*List<SyntaxException> exceptions = new List<SyntaxException>();
+               public IEnumerable<SyntaxException> Exceptions => exceptions;
+               public void AddException(SyntaxException e) => exceptions.Add(e);
+               public void ResetExceptions(SyntaxException e) => exceptions.Clear();
+               public IEnumerable<SyntaxException> GetAllExceptions() {
+                               foreach (SyntaxException e in exceptions)
+                                       yield return e;
+                               foreach (SyntaxNode n in Children) {
+                                       foreach (SyntaxException ce in n.GetAllExceptions())
+                                               yield return ce;
+                               }
+               }*/
+       
+               //public int IndexOf (SyntaxNode node) => children.IndexOf (node);
+
+               /*public virtual int TokenIndexBase { get; private set; }
+               public virtual int TokenCount => lastTokenOfset.HasValue ? lastTokenOfset.Value + 1 : 0;
+               public int? LastTokenIndex =>  lastTokenOfset.HasValue ? TokenIndexBase + lastTokenOfset.Value : null;
+
+               public int EndLine {
+                       set {
+                               lineCount = value - StartLine + 1;
+                       }
+                       get => StartLine + lineCount - 1;
+               }*/
+
+               /*
+               public void Replace (SyntaxNode newNode) {
+                       Parent.replaceChild (this, newNode);
+               }
+               void replaceChild (SyntaxNode oldNode, SyntaxNode newNode) {
+                       int idx = children.IndexOf (oldNode);
+                       children[idx] = newNode;
+                       newNode.Parent = this;
+                       int tokIdxDiff = newNode.TokenCount - oldNode.TokenCount;
+                       int lineDiff = newNode.EndLine - oldNode.EndLine;
+                       if (tokIdxDiff == 0 && lineDiff == 0)
+                               return;
+
+                       SyntaxNode curNode = this;
+                       while (curNode != null) {
+                               curNode.lineCount += lineDiff;
+                               curNode.TokenCount += tokIdxDiff;
+                               if (curNode is SyntaxRootNode)
+                                       break;
+                               while (++idx < curNode.children.Count)
+                                       curNode.children[idx].offset (tokIdxDiff, lineDiff);
+                               idx = curNode.Parent.children.IndexOf (curNode);
+                               curNode = curNode.Parent;
+                       }
+               }*/
+               /*void offset (int tokenOffset, int lineOffset) {
+                       TokenIndexBase += tokenOffset;
+                       StartLine += lineOffset;
+                       foreach (SyntaxNode child in children) {
+                               child.offset (tokenOffset, lineOffset);
+                       }
+               }*/
+/*             
+               public T FindNodeIncludingPosition<T> (int pos) {
+                       foreach (SyntaxNode node in children) {
+                               if (node.Contains (pos))
+                                       return node.FindNodeIncludingPosition<T> (pos);
+                       }
+
+                       return this is T tt ? tt : default;
+               }*/
+               /*public void Dump (int level = 0) {
+                       Console.WriteLine ($"{new string('\t', level)}{this}");
+                       foreach (SyntaxNode node in children)
+                               node.Dump (level + 1);
+               }*/
+               //public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{TokenCount} {this.GetType().Name}";
+               #endregion
+    }
+}
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxNodes/SyntaxRootNode.cs b/CrowEditBase/src/Compiler/SyntaxNodes/SyntaxRootNode.cs
new file mode 100644 (file)
index 0000000..2e7bf84
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using Crow.Text;
+
+namespace CrowEditBase
+{
+       public abstract class SyntaxRootNode : MultiNodeSyntax {
+               #region CTOR
+               public SyntaxRootNode (ReadOnlyTextBuffer buffer, Token[] tokens) {
+                       this.buffer = buffer;
+                       this.tokens = tokens;
+               }
+               #endregion
+
+               protected readonly ReadOnlyTextBuffer buffer;
+               protected Token[] tokens;
+               public ReadOnlySpan<Token> Tokens => tokens;
+               
+               public override SyntaxRootNode Root => this;
+               public override bool IsFoldable => false;
+               public override void UnfoldToTheTop() {}
+               public override SyntaxNode NextSiblingOrParentsNextSibling => null;
+
+
+
+               public string GetTokenStringByIndex (int idx) => tokens != null ?
+                       idx >= 0 && idx < tokens.Length ? GetText(tokens[idx].Span).ToString() : null : null;
+               public Token GetTokenByIndex (int idx) => tokens != null ?
+                       idx >= 0 && idx < tokens.Length ? tokens[idx] : default : default;
+               public int FindTokenIndexIncludingPosition (int pos) {
+                       if (pos == 0 || Tokens.Length == 0)
+                               return default;
+                       int idx = Tokens.BinarySearch(new  Token (pos));
+                       return idx == 0 ? 0 : idx < 0 ? ~idx - 1 : idx;
+               }
+               public ReadOnlySpan<char> GetText(TextSpan span) =>
+                       buffer.Source.Span.Slice(span.Start, span.Length);
+               public CharLocation GetLocation(int pos) => buffer.Lines.GetLocation(pos);
+                       
+               public string GetTokenString(Token tok) =>
+                       GetText(tok.Span).ToString();
+       }
+}
\ No newline at end of file
diff --git a/CrowEditBase/src/Compiler/SyntaxRootNode.cs b/CrowEditBase/src/Compiler/SyntaxRootNode.cs
deleted file mode 100644 (file)
index 2c177e2..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using Crow.Text;
-
-namespace CrowEditBase
-{
-       public abstract class SyntaxRootNode : MultiNodeSyntax {
-               public SyntaxRootNode (ReadOnlyTextBuffer buffer, Token[] tokens) {
-                       this.buffer = buffer;
-                       this.tokens = tokens;
-               }
-               protected readonly ReadOnlyTextBuffer buffer;
-               protected Token[] tokens;
-               public override SyntaxRootNode Root => this;
-
-
-               public override bool IsFoldable => false;
-               public override void UnfoldToTheTop() {}
-               public override SyntaxNode NextSiblingOrParentsNextSibling => null;
-
-               public ReadOnlySpan<Token> Tokens => tokens;
-
-
-               public string GetTokenStringByIndex (int idx) => tokens != null ?
-                       idx >= 0 && idx < tokens.Length ? GetText(tokens[idx].Span).ToString() : null : null;
-               public Token GetTokenByIndex (int idx) => tokens != null ?
-                       idx >= 0 && idx < tokens.Length ? tokens[idx] : default : default;
-               public int FindTokenIndexIncludingPosition (int pos) {
-                       if (pos == 0 || Tokens.Length == 0)
-                               return default;
-                       int idx = Tokens.BinarySearch(new  Token (pos));
-                       return idx == 0 ? 0 : idx < 0 ? ~idx - 1 : idx;
-               }
-               public ReadOnlySpan<char> GetText(TextSpan span) =>
-                       buffer.Source.Span.Slice(span.Start, span.Length);
-               public CharLocation GetLocation(int pos) => buffer.Lines.GetLocation(pos);
-                       
-               public string GetTokenString(Token tok) =>
-                       GetText(tok.Span).ToString();
-       }
-}
\ No newline at end of file
index d4a032b51880aeb3b8c5150af0d606efefc40a85..4dd192b6e8a6039f6b2a836ca2b671a9d1614a2c 100644 (file)
@@ -13,11 +13,17 @@ using static CrowEditBase.CrowEditBase;
 namespace CrowEditBase
 {
        public abstract class Document : CrowEditComponent {
+               #region CTOR
                public Document (string fullPath, string editorPath) {
                        initCommands ();
                        EditorPath = editorPath;
                        FullPath = fullPath;
                }
+               #endregion
+
+               DateTime accessTime;
+               string fullPath;
+
                /// <summary>
                /// Editor used to open the document, can't be changed once opened
                /// </summary>
@@ -34,12 +40,7 @@ namespace CrowEditBase
                public void EnterWriteLock () => documentRWLock.EnterWriteLock ();
                public void ExitWriteLock () => documentRWLock.ExitWriteLock ();
 
-               public abstract bool TryGetState<T> (object client, out T state);
-               public abstract void RegisterClient (object client, bool initialState = false);
-               public abstract void UnregisterClient (object client);
 
-               DateTime accessTime;
-               string fullPath;
 
                public string FullPath {
                        get => fullPath;
@@ -60,25 +61,9 @@ namespace CrowEditBase
                public string Extension => System.IO.Path.GetExtension (FullPath);
                public bool ExternalyModified => File.Exists (FullPath) ?
                        (DateTime.Compare (accessTime, System.IO.File.GetLastWriteTime (FullPath)) < 0) : false;
-               public void OnQueryClose (object sender, EventArgs e){
-                       CloseEvent.Raise (this, null);
-               }
-               protected abstract void saveFileDialog_OkClicked (object sender, EventArgs e);
-               public void SaveAs () {
-                       App.LoadIMLFragment (
-                       @"<FileDialog Width='60%' Height='50%' Caption='Save File' CurrentDirectory='{FileDirectory}'
-                               SelectedFile='{FileName}' OkClicked='saveFileDialog_OkClicked'/>"
-                       ).DataSource = this;
-               }
-               public void Save () {
-                       if (File.Exists (FullPath))
-                               writeToDisk ();
-                       else
-                               SaveAs ();
-               }
 
+               #region commands
                public Command CMDUndo, CMDRedo, CMDSave, CMDSaveAs;
-
                Command CMDClose, CMDCloseOther;
                public CommandGroup TabCommands => new CommandGroup (
                        CMDClose, CMDCloseOther
@@ -92,11 +77,19 @@ namespace CrowEditBase
                        CMDClose = new ActionCommand ("Close", () => App.CloseDocument (this), "#icons.sign-out.svg");
                        CMDCloseOther = new ActionCommand ("Close Others", () => App.CloseOthers (this), "#icons.inbox.svg");
                }
+               #endregion
+
+               public abstract bool TryGetState<T> (object client, out T state);
+               public abstract void RegisterClient (object client, bool initialState = false);
+               public abstract void UnregisterClient (object client);
+               protected abstract void saveFileDialog_OkClicked (object sender, EventArgs e);
                protected abstract void undo();
                protected abstract void redo();
                protected abstract void writeToDisk ();
                protected abstract void readFromDisk ();
                protected abstract void initNewFile ();
+               public abstract bool IsDirty { get; }
+
                protected virtual void reloadFromFile () {
                        documentRWLock.EnterWriteLock ();
                        try {
@@ -108,7 +101,21 @@ namespace CrowEditBase
                                documentRWLock.ExitWriteLock ();
                        }
                }
-               public abstract bool IsDirty { get; }
+               public void OnQueryClose (object sender, EventArgs e){
+                       CloseEvent.Raise (this, null);
+               }
+               public void SaveAs () {
+                       App.LoadIMLFragment (
+                       @"<FileDialog Width='60%' Height='50%' Caption='Save File' CurrentDirectory='{FileDirectory}'
+                               SelectedFile='{FileName}' OkClicked='saveFileDialog_OkClicked'/>"
+                       ).DataSource = this;
+               }
+               public void Save () {
+                       if (File.Exists (FullPath))
+                               writeToDisk ();
+                       else
+                               SaveAs ();
+               }
 
                public override string ToString() => FullPath;
 
index fec865ef850c6326978cdfc6ce18ff311f699ac1..9f4603dba62ceacc898e6662509e79d2044a65a8 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2021  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+// Copyright (c) 2021-2025  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
@@ -21,21 +21,28 @@ namespace CrowEditBase
                }
        }
        public class TextDocument : Document {
+               #region CTOR
                public TextDocument (string fullPath, string editorPath = "default")
                        : base (fullPath, editorPath) {
                        reloadFromFile ();
                }
+               #endregion
 
                protected TextBuffer buffer;
-               public ReadOnlySpan<char> source => buffer.ReadOnlySpan;
-
-               public ReadOnlyTextBuffer ImmutableBufferCopy => new ReadOnlyTextBuffer(buffer.ReadOnlyCopy, buffer.GetLineListCopy());
+               protected Stack<TextChange> undoStack = new Stack<TextChange> ();
+               protected Stack<TextChange> redoStack = new Stack<TextChange> ();
                System.Text.Encoding encoding = System.Text.Encoding.UTF8;
+               Dictionary<object, List<TextChange>> registeredClients =
+                       new Dictionary<object, List<TextChange>>();     // dictionnary of object per document client, when not null, client must reload content of document.
+               protected bool disableTextChangedEvent = false;
+
                public event EventHandler<TextChangeEventArgs> TextChanged;
 
+               public ReadOnlySpan<char> source => buffer.ReadOnlySpan;
+               public ReadOnlyTextBuffer ImmutableBufferCopy => new ReadOnlyTextBuffer(buffer.ReadOnlyCopy, buffer.GetLineListCopy());
+
+               #region Document interface implementation
                public override bool IsDirty => buffer.IsDirty;
-                               /// dictionnary of object per document client, when not null, client must reload content of document.
-               Dictionary<object, List<TextChange>> registeredClients = new Dictionary<object, List<TextChange>>();
                public override bool TryGetState<T>(object client, out T state) {
                        state = default;
                        if (documentRWLock.TryEnterReadLock (10)) {
@@ -62,23 +69,6 @@ namespace CrowEditBase
                        registeredClients.Remove (client);
                        ExitWriteLock();
                }
-               protected void notifyClients (TextChange tc, object triggeringClient = null) {
-                       object[] clients = registeredClients.Keys.ToArray ();
-                       for (int i = 0; i < clients.Length; i++) {
-                               if (clients[i] != triggeringClient)
-                                       notifyClient (clients[i], tc);
-                       }
-               }
-               protected void notifyClient (object client, TextChange tc) {
-                       if (registeredClients[client] == null)
-                               registeredClients[client] = new List<TextChange> ();
-                       registeredClients[client].Add (tc);
-               }
-
-               public virtual void SetLocation(CharLocation loc) {
-                       notifyClients(new TextChange(GetAbsolutePosition(loc),0));
-               }
-
                protected override void writeToDisk () {
                        using (Stream s = new FileStream(FullPath, FileMode.Create)) {
                                using (StreamWriter sw = new StreamWriter (s, encoding))
@@ -113,8 +103,6 @@ namespace CrowEditBase
                                documentRWLock.ExitWriteLock ();
                        }
                }
-               protected Stack<TextChange> undoStack = new Stack<TextChange> ();
-               protected Stack<TextChange> redoStack = new Stack<TextChange> ();
                protected override void saveFileDialog_OkClicked (object sender, EventArgs e)
                {
                        FileDialog fd = sender as FileDialog;
@@ -166,19 +154,25 @@ namespace CrowEditBase
                        }
 
                }
+               #endregion
+               
                protected void resetUndoRedo () {
                        undoStack.Clear ();
                        redoStack.Clear ();
                        CMDUndo.CanExecute = false;
                        CMDRedo.CanExecute = false;
                }
-               protected bool disableTextChangedEvent = false;
-               protected virtual void apply (TextChange change) {
-
-                       buffer.Update(change);
-
-                       NotifyValueChanged ("IsDirty", IsDirty);
-                       CMDSave.CanExecute = IsDirty;                   
+               protected void notifyClients (TextChange tc, object triggeringClient = null) {
+                       object[] clients = registeredClients.Keys.ToArray ();
+                       for (int i = 0; i < clients.Length; i++) {
+                               if (clients[i] != triggeringClient)
+                                       notifyClient (clients[i], tc);
+                       }
+               }
+               protected void notifyClient (object client, TextChange tc) {
+                       if (registeredClients[client] == null)
+                               registeredClients[client] = new List<TextChange> ();
+                       registeredClients[client].Add (tc);
                }
                protected void applyTextChange (TextChange change, object triggeringEditor = null) {
                        documentRWLock.EnterWriteLock ();
@@ -301,6 +295,16 @@ namespace CrowEditBase
                        }
                }
 
+               protected virtual void apply (TextChange change) {
+
+                       buffer.Update(change);
+
+                       NotifyValueChanged ("IsDirty", IsDirty);
+                       CMDSave.CanExecute = IsDirty;                   
+               }
+               public virtual void SetLocation(CharLocation loc) {
+                       notifyClients(new TextChange(GetAbsolutePosition(loc),0));
+               }
                public virtual CharLocation GetWordStart (CharLocation loc) {
                        documentRWLock.EnterReadLock ();
                        try {
diff --git a/plugins/CERoslynPlugin/src/CSSyntaxAnalyser.cs b/plugins/CERoslynPlugin/src/CSSyntaxAnalyser.cs
deleted file mode 100644 (file)
index 085e5a6..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
-//
-// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Crow.Text;
-using CrowEditBase;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Text;
-
-namespace CERoslynPlugin
-{
-       public class CSRootSyntax : SyntaxRootNode {
-               public CSRootSyntax (ReadOnlyTextBuffer source) : base (source, null) { }
-               internal void SetTokens(Token[] tokens) {
-                       this.tokens = tokens;
-               }
-       }
-       public class CSToken : SingleTokenSyntax {
-               SyntaxToken cstoken;
-               public CSToken(SyntaxToken token, Token tok) : base (tok) {
-                       cstoken = token;
-               }
-               public override string ToString() => $"TOK: {cstoken.Kind()}";
-       }
-       public class CSTrivia : SingleTokenSyntax {
-               SyntaxTrivia cstrivia;
-               public CSTrivia(SyntaxTrivia token, Token tok) : base (tok) {
-                       cstrivia = token;
-               }
-               public override string ToString() => $"Trivia: {cstrivia.Kind()}";
-       }       
-       public class CSSyntaxNode : MultiNodeSyntax {
-               Microsoft.CodeAnalysis.SyntaxNode node;
-               public CSSyntaxNode(Microsoft.CodeAnalysis.SyntaxNode node) {
-                       this.node = node;
-               }
-               public override string ToString() => $"{node.Kind()}";
-
-    }
-       
-       public class CSSyntaxAnalyser : SyntaxAnalyser {
-        /*protected override void Parse(SyntaxNode node)
-        {
-            throw new NotImplementedException();
-        }*/
-               CSDocument csdoc;
-               public CSSyntaxAnalyser (CSDocument document) : base (document) {
-                       csdoc = document;
-               }
-
-               public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
-                       ReadOnlyTextBuffer buff = document.ImmutableBufferCopy;
-                       CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge(new CSRootSyntax (buff), cancel);
-                       CSharpSyntaxNode csroot = await csdoc.tree.GetRootAsync(cancel);
-
-                       if (cancel.IsCancellationRequested)
-                               return null;
-
-                       bridge.Visit(csroot);
-                       bridge.Root.SetTokens (bridge.Toks.ToArray());
-                       Root = bridge.Root;
-                       return Root;
-               }
-       }
-       class CsharpSyntaxWalkerBridge : CSharpSyntaxWalker
-       {
-               public CSRootSyntax Root;
-               public List<Token> Toks;
-               MultiNodeSyntax currentNode;
-               CancellationToken cancel;
-               public CsharpSyntaxWalkerBridge (CSRootSyntax root, CancellationToken cancel = default) : base (SyntaxWalkerDepth.StructuredTrivia)
-               {
-                       this.cancel = cancel;
-                       currentNode = Root = root;
-                       Toks = new List<Token>(100);
-               }
-               public override void Visit (Microsoft.CodeAnalysis.SyntaxNode node)
-               {
-                       if (cancel.IsCancellationRequested)
-                               return;
-                       currentNode = currentNode.AddChild(new CSSyntaxNode(node)) as MultiNodeSyntax;
-                       
-                       base.Visit (node);
-
-                       currentNode = currentNode.Parent;
-               }
-
-        /*public override void VisitToken(SyntaxToken token)
-        {
-                       
-            base.VisitToken(token);
-        }*/
-
-               public override void VisitToken (SyntaxToken token)
-               {
-                       if (cancel.IsCancellationRequested)
-                               return;
-
-                       VisitLeadingTrivia (token);
-
-                       Microsoft.CodeAnalysis.Text.TextSpan fs = token.Span;
-                       /*if (SyntaxFacts.IsLiteralExpression (token.Kind ()))
-                               addMultilineToken(token.ToString(), token.Span, (TokenType)token.RawKind);
-                       else*/
-                       if (fs.Length == 0)
-                               Debug.WriteLine($"Empty token: {token}");
-                       else {
-                               Microsoft.CodeAnalysis.Text.TextSpan span = token.Span;
-                               Token tok = new Token(fs.Start,fs.Length,(TokenType)token.RawKind);
-                               Toks.Add(tok);
-                               currentNode.AddChild(new CSToken(token, tok));
-                       }
-
-                       VisitTrailingTrivia (token);
-               }
-               
-        public override void VisitTrivia (SyntaxTrivia trivia)
-               {
-                       if (cancel.IsCancellationRequested)
-                               return;
-
-                       SyntaxKind kind = trivia.Kind ();
-                       Microsoft.CodeAnalysis.Text.TextSpan span = trivia.Span;
-                       if (kind == SyntaxKind.EndOfLineTrivia) {
-                               Toks.Add (new Token(span.Start, span.Length, TokenType.LineBreak));
-                               return;
-                       }
-                       if (trivia.HasStructure)
-                               this.Visit ((CSharpSyntaxNode)trivia.GetStructure());
-                       else if (trivia.IsKind (SyntaxKind.DisabledTextTrivia) || trivia.IsKind (SyntaxKind.MultiLineCommentTrivia))
-                addMultilineToken(trivia.ToString(), trivia.Span, (TokenType)trivia.RawKind);
-                       else {
-                               Toks.Add (new Token(span.Start, span.Length, (TokenType)trivia.RawKind));
-                       }
-               }
-               int startOfTok;
-               void addTok (ref SpanCharReader reader, int offset, Enum tokType) {
-                       if (reader.CurrentPosition == startOfTok)
-                               return;
-                       Token tok = new Token((TokenType)tokType,startOfTok + offset, reader.CurrentPosition + offset);
-                       Toks.Add (tok);
-                       currentNode.AddChild(new CSToken(default, tok));
-
-                       startOfTok = reader.CurrentPosition;
-               }               
-               void addMultilineToken(ReadOnlySpan<char> txt, Microsoft.CodeAnalysis.Text.TextSpan span, TokenType mainType) {
-                       SpanCharReader reader = new SpanCharReader(txt);
-                       startOfTok = 0;
-
-                       while(!reader.EndOfSpan) {
-                               if (cancel.IsCancellationRequested)
-                                       return;
-                               switch (reader.Peek) {
-                                       case '\x85':
-                                       case '\x2028':
-                                       case '\xA':
-                                               addTok (ref reader, span.Start, mainType);
-                                               reader.Read();
-                                               addTok (ref reader, span.Start, TokenType.LineBreak);
-                                               break;
-                                       case '\xD':
-                                               addTok (ref reader, span.Start, mainType);
-                                               reader.Read();
-                                               if (reader.IsNextCharIn ('\xA', '\x85'))
-                                                       reader.Read();
-                                               addTok (ref reader, span.Start, TokenType.LineBreak);
-                                               break;
-                                       case '\x20':
-                                       case '\x9':
-                                               addTok (ref reader, span.Start, mainType);
-                                               char c = reader.Read();
-                                               while (reader.TryPeek (c))
-                                                       reader.Read();
-                                               addTok (ref reader, span.Start, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
-                                               break;
-                                       default:
-                                               reader.Read();
-                                               break;
-                               }
-                       }                       
-                       addTok (ref reader, span.Start, mainType);
-               }                               
-    }
-}
\ No newline at end of file
diff --git a/plugins/CERoslynPlugin/src/Parsing/CSSyntaxAnalyser.cs b/plugins/CERoslynPlugin/src/Parsing/CSSyntaxAnalyser.cs
new file mode 100644 (file)
index 0000000..e797873
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Threading;
+using System.Threading.Tasks;
+using CrowEditBase;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace CERoslynPlugin
+{
+       public class CSSyntaxAnalyser : SyntaxAnalyser {
+               CSDocument csdoc;
+               public CSSyntaxAnalyser (CSDocument document) : base (document) {
+                       csdoc = document;
+               }
+
+               public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
+                       ReadOnlyTextBuffer buff = document.ImmutableBufferCopy;
+                       CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge(new CSRootSyntax (buff), cancel);
+                       CSharpSyntaxNode csroot = await csdoc.tree.GetRootAsync(cancel);
+
+                       if (cancel.IsCancellationRequested)
+                               return null;
+
+                       bridge.Visit(csroot);
+                       bridge.Root.SetTokens (bridge.Toks.ToArray());
+                       Root = bridge.Root;
+                       return Root;
+               }
+       }
+}
\ No newline at end of file
diff --git a/plugins/CERoslynPlugin/src/Parsing/CsharpSyntaxWalkerBridge.cs b/plugins/CERoslynPlugin/src/Parsing/CsharpSyntaxWalkerBridge.cs
new file mode 100644 (file)
index 0000000..c276670
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using Crow.Text;
+using CrowEditBase;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace CERoslynPlugin
+{
+       class CsharpSyntaxWalkerBridge : CSharpSyntaxWalker
+       {
+               #region CTOR
+               public CsharpSyntaxWalkerBridge (CSRootSyntax root, CancellationToken cancel = default) : base (SyntaxWalkerDepth.StructuredTrivia)
+               {
+                       this.cancel = cancel;
+                       currentNode = Root = root;
+                       Toks = new List<Token>(100);
+               }
+               #endregion
+
+               public CSRootSyntax Root;
+               public List<Token> Toks;
+               MultiNodeSyntax currentNode;
+               int startOfTok;
+               CancellationToken cancel;
+
+               public override void Visit (Microsoft.CodeAnalysis.SyntaxNode node)
+               {
+                       if (cancel.IsCancellationRequested)
+                               return;
+                       currentNode = currentNode.AddChild(new CSSyntaxNode(node)) as MultiNodeSyntax;
+                       
+                       base.Visit (node);
+
+                       currentNode = currentNode.Parent;
+               }
+               public override void VisitToken (SyntaxToken token)
+               {
+                       if (cancel.IsCancellationRequested)
+                               return;
+
+                       VisitLeadingTrivia (token);
+
+                       Microsoft.CodeAnalysis.Text.TextSpan fs = token.Span;
+                       /*if (SyntaxFacts.IsLiteralExpression (token.Kind ()))
+                               addMultilineToken(token.ToString(), token.Span, (TokenType)token.RawKind);
+                       else*/
+                       if (fs.Length == 0)
+                               Debug.WriteLine($"Empty token: {token}");
+                       else {
+                               Microsoft.CodeAnalysis.Text.TextSpan span = token.Span;
+                               Token tok = new Token(fs.Start,fs.Length,(TokenType)token.RawKind);
+                               Toks.Add(tok);
+                               currentNode.AddChild(new CSToken(token, tok));
+                       }
+
+                       VisitTrailingTrivia (token);
+               }
+        public override void VisitTrivia (SyntaxTrivia trivia)
+               {
+                       if (cancel.IsCancellationRequested)
+                               return;
+
+                       SyntaxKind kind = trivia.Kind ();
+                       Microsoft.CodeAnalysis.Text.TextSpan span = trivia.Span;
+                       if (kind == SyntaxKind.EndOfLineTrivia) {
+                               Toks.Add (new Token(span.Start, span.Length, TokenType.LineBreak));
+                               return;
+                       }
+                       if (trivia.HasStructure)
+                               this.Visit ((CSharpSyntaxNode)trivia.GetStructure());
+                       else if (trivia.IsKind (SyntaxKind.DisabledTextTrivia) || trivia.IsKind (SyntaxKind.MultiLineCommentTrivia))
+                addMultilineToken(trivia.ToString(), trivia.Span, (TokenType)trivia.RawKind);
+                       else {
+                               Toks.Add (new Token(span.Start, span.Length, (TokenType)trivia.RawKind));
+                       }
+               }
+               
+               void addTok (ref SpanCharReader reader, int offset, Enum tokType) {
+                       if (reader.CurrentPosition == startOfTok)
+                               return;
+                       Token tok = new Token((TokenType)tokType,startOfTok + offset, reader.CurrentPosition + offset);
+                       Toks.Add (tok);
+                       currentNode.AddChild(new CSToken(default, tok));
+
+                       startOfTok = reader.CurrentPosition;
+               }               
+               void addMultilineToken(ReadOnlySpan<char> txt, Microsoft.CodeAnalysis.Text.TextSpan span, TokenType mainType) {
+                       SpanCharReader reader = new SpanCharReader(txt);
+                       startOfTok = 0;
+
+                       while(!reader.EndOfSpan) {
+                               if (cancel.IsCancellationRequested)
+                                       return;
+                               switch (reader.Peek) {
+                                       case '\x85':
+                                       case '\x2028':
+                                       case '\xA':
+                                               addTok (ref reader, span.Start, mainType);
+                                               reader.Read();
+                                               addTok (ref reader, span.Start, TokenType.LineBreak);
+                                               break;
+                                       case '\xD':
+                                               addTok (ref reader, span.Start, mainType);
+                                               reader.Read();
+                                               if (reader.IsNextCharIn ('\xA', '\x85'))
+                                                       reader.Read();
+                                               addTok (ref reader, span.Start, TokenType.LineBreak);
+                                               break;
+                                       case '\x20':
+                                       case '\x9':
+                                               addTok (ref reader, span.Start, mainType);
+                                               char c = reader.Read();
+                                               while (reader.TryPeek (c))
+                                                       reader.Read();
+                                               addTok (ref reader, span.Start, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
+                                               break;
+                                       default:
+                                               reader.Read();
+                                               break;
+                               }
+                       }                       
+                       addTok (ref reader, span.Start, mainType);
+               }                               
+    }
+}
\ No newline at end of file
diff --git a/plugins/CERoslynPlugin/src/Parsing/SyntaxNodes.cs b/plugins/CERoslynPlugin/src/Parsing/SyntaxNodes.cs
new file mode 100644 (file)
index 0000000..3f6f267
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using CrowEditBase;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace CERoslynPlugin
+{
+       public class CSRootSyntax : SyntaxRootNode {
+               public CSRootSyntax (ReadOnlyTextBuffer source) : base (source, null) { }
+               internal void SetTokens(Token[] tokens) {
+                       this.tokens = tokens;
+               }
+       }
+       public class CSToken : SingleTokenSyntax {
+               SyntaxToken cstoken;
+               public CSToken(SyntaxToken token, Token tok) : base (tok) {
+                       cstoken = token;
+               }
+               public override string ToString() => $"TOK: {cstoken.Kind()}";
+       }
+       public class CSTrivia : SingleTokenSyntax {
+               SyntaxTrivia cstrivia;
+               public CSTrivia(SyntaxTrivia token, Token tok) : base (tok) {
+                       cstrivia = token;
+               }
+               public override string ToString() => $"Trivia: {cstrivia.Kind()}";
+       }       
+       public class CSSyntaxNode : MultiNodeSyntax {
+               Microsoft.CodeAnalysis.SyntaxNode node;
+               public CSSyntaxNode(Microsoft.CodeAnalysis.SyntaxNode node) {
+                       this.node = node;
+               }
+               public override string ToString() => $"{node.Kind()}";
+
+    }
+}
\ No newline at end of file
index e5da95d41ecae0c8c027693b3f6f9809e63b4169..4fc91f1bc7f02ca513422f6fc67ce779518c6366 100644 (file)
@@ -61,7 +61,4 @@ namespace CrowEdit.Xml
                        AddChild (new SingleTokenSyntax(name));
                }
        }
-       /*public class AttributeNameSyntax : SingleTokenSyntax {
-               public AttributeNameSyntax(Token name) : base(name) {}
-       }*/     
 }
\ No newline at end of file