using System.Collections.Generic;
using Drawing2D;
using System.Security;
+using System.Threading;
+using System.Threading.Tasks;
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 () {
- SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
- root = await syntaxAnalyser.Process ();
+ if (backgroundCompilationTask != null && !backgroundCompilationTask.IsCompleted) {
+ cancelSource.Cancel();
+ await backgroundCompilationTask;
+ }
- NotifyValueChanged("Exceptions", syntaxAnalyser?.Exceptions);
- NotifyValueChanged ("SyntaxRootChildNodes", (object)null);
- NotifyValueChanged ("SyntaxRootChildNodes", SyntaxRootChildNodes);
+ cancelSource = new CancellationTokenSource();
+ backgroundCompilationTask = Task.Run(()=>parseAssync(cancelSource.Token));
//CurrentNode?.ExpandToTheTop();
//CrowEditBase.App.Log (LogType.Low, $"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
}
+ async void parseAssync(CancellationToken cancel) {
+ SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
+ root = await syntaxAnalyser.Process (cancel);
+ if (cancel.IsCancellationRequested)
+ return;
+
+ NotifyValueChanged("Exceptions", syntaxAnalyser?.Exceptions);
+ NotifyValueChanged ("SyntaxRootChildNodes", (object)null);
+ NotifyValueChanged ("SyntaxRootChildNodes", SyntaxRootChildNodes);
+ }
+
public SyntaxException CurrentException {
get => CrowEditBase.App.CurrentException;
set {
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using Crow.Text;
public SyntaxAnalyser (SourceDocument document) {
this.document = document;
}
- public abstract Task<SyntaxRootNode> Process ();
+ public abstract Task<SyntaxRootNode> Process (CancellationToken cancel = default);
#region Token handling
protected Token curTok => tokIdx < 0 ? default : tokens[tokIdx];
}
}
}
+
public virtual int FoldedLineCount {
get {
if (isFolded)
CMDCopy.CanExecute = CMDCut.CanExecute = !SelectionIsEmpty;
}
}
- public int CurrentColumn {
+ public int CurrentColumn {
get => currentLoc.HasValue ? currentLoc.Value.Column < 0 ? 0 : currentLoc.Value.Column : 0;
set {
if (CurrentColumn == value)
}
protected int getLineIndexFromMousePosition (Point mouseLocalPos) =>
(int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ lineHeight)), visualLineCount - 1);
+ protected int getLineIndexFromMousePositionUnchecked (Point mouseLocalPos) =>
+ (int)Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ lineHeight));
protected int getVisualLineIndex (Point mouseLocalPos) =>
(int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / lineHeight)), visibleLines - 1);
protected virtual int visualCurrentLine => CurrentLoc.HasValue ? CurrentLoc.Value.Line : 0;
using System.Linq;
using System.Text.Unicode;
using System.Text;
+using System.Threading.Tasks;
namespace CrowEditBase
{
}
int currentTokenIndex = -1;
SyntaxNode currentNode;
-#if DEBUG_NODE
+/*#if DEBUG_NODE
SyntaxNode _hoverNode;
SyntaxNode hoverNode {
get =>_hoverNode;
RegisterForRedraw ();
}
}
-#endif
+#endif*/
public SyntaxNode CurrentNode {
get => currentNode;
set {
}
}
+ //Task<int> taskFirstVisibleLineIndex;
+
#region Mouse & Keyboard overrides
public override void onMouseDown (object sender, MouseButtonEventArgs e) {
hideOverlay ();
mouseIsInMargin = mouseIsInFoldRect = false;
IFace.MouseCursor = MouseCursor.ibeam;
}
+
+ int hoverVisualLine = getLineIndexFromMousePositionUnchecked (mLoc);
+ int hoverLine = getAbsoluteLineFromVisualLine (hoverVisualLine);
+
+ /***************************/
+ /*hoverLoc = new CharLocation (hoverLine, -1, mLoc.X + ScrollX - leftMargin);
+ using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+ updateLocation (gr, ref hoverLoc);
+ }*/
+ /***************************/
+
+ NotifyValueChanged("MouseY", mLoc.Y + ScrollY);
+ NotifyValueChanged("hoverVisualLine", hoverVisualLine);
+ NotifyValueChanged("hoverLine", hoverLine);
- updateHoverLocation (mLoc);
+
+ if (mouseIsInMargin) {
+ if (hoverLoc.HasValue)
+ hoverLoc = new CharLocation (hoverLine, hoverLoc.Value.Column, hoverLoc.Value.VisualCharXPosition);
+ else
+ hoverLoc = new CharLocation (hoverLine, 0, 0);
+ } else {
+ hoverLoc = new CharLocation (hoverLine, -1, mLoc.X + ScrollX - leftMargin);
+ using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+ updateLocation (gr, ref hoverLoc);
+ }
+ }
if (mouseIsInMargin) {
Rectangle rFold = new Rectangle (leftMargin - foldMargin - leftMarginRightGap,
- (int)(lineHeight * getVisualLine(hoverLoc.Value.Line) + lineHeight / 2.0 - foldSize / 2.0) - ScrollY, foldSize, foldSize);
+ (int)(lineHeight * hoverVisualLine + lineHeight / 2.0 - foldSize / 2.0) - ScrollY, foldSize, foldSize);
rFold.Inflate(2);
mouseIsInFoldRect = rFold.ContainsOrIsEqual (mLoc);
RegisterForRedraw();
}
}
protected override void updateHoverLocation (Point mouseLocalPos) {
- int hoverVisualLine = getLineIndexFromMousePosition (mouseLocalPos);
- int hoverLine = hoverVisualLine + countFoldedLinesUntil (hoverVisualLine);
- NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY);
- NotifyValueChanged("ScrollY", ScrollY);
- NotifyValueChanged("VisibleLines", visibleLines);
- NotifyValueChanged("HoverLine", hoverLine);
+ int hoverVisualLine = getLineIndexFromMousePositionUnchecked (mouseLocalPos);
+ int hoverLine = getAbsoluteLineFromVisualLine (hoverVisualLine);
+
if (mouseIsInMargin) {
if (hoverLoc.HasValue)
hoverLoc = new CharLocation (hoverLine, hoverLoc.Value.Column, hoverLoc.Value.VisualCharXPosition);
gr.SetFontSize (Font.Size);
updateLocation (gr, ref hoverLoc);
}
-#if DEBUG_NODES
+/*#if DEBUG_NODES
if (Document is SourceDocument doc) {
hoverNode = doc.FindNodeIncludingPosition (lines.GetAbsolutePosition (hoverLoc.Value));
}
-#endif
+#endif*/
}
public override void onKeyDown(object sender, KeyEventArgs e)
{
}
}
- int getVisualLine (int absoluteLine) {
+ int getVisualLineFromAboluteLine (int absoluteLine) {
if (!(Document is SourceDocument doc))
return absoluteLine;
doc.EnterReadLock();
doc.ExitReadLock ();
}
}
- int countFoldedLinesUntil (int visualLine) {
+ int getAbsoluteLineFromVisualLine (int visualLine) {
if (!(Document is SourceDocument doc))
return 0;
doc.EnterReadLock();
try {
- int foldedLines = 0;
if (!doc.IsParsed)
return 0;
- IEnumerator<MultiNodeSyntax> nodeEnum = doc.Root.VisibleFoldableNodes.GetEnumerator ();
- if (!nodeEnum.MoveNext())
- return 0;
- int l = 0;
- while (l < visualLine + foldedLines) {
- if (nodeEnum.Current.StartLocation.Line == l) {
- if (nodeEnum.Current.isFolded) {
- foldedLines += nodeEnum.Current.LineCount - 1;
- SyntaxNode nextNode = nodeEnum.Current.NextSiblingOrParentsNextSibling;
- if (nextNode == null || !nodeEnum.MoveNext())
- return foldedLines;
-
- while (nodeEnum.Current.StartLocation.Line < nextNode.StartLocation.Line) {
- if (!nodeEnum.MoveNext())
- return foldedLines;
- }
+ int linesToSkip = visualLine;
+ IEnumerator<MultiNodeSyntax> foldsEnum = doc.Root.VisibleFoldableNodes.GetEnumerator ();
+ bool notEndOfFolds = foldsEnum.MoveNext();
- } else if (!nodeEnum.MoveNext())
- return foldedLines;
- }
- l ++;
+ while (notEndOfFolds && foldsEnum.Current.StartLocation.Line < linesToSkip) {
+ if (foldsEnum.Current.isFolded)
+ linesToSkip += foldsEnum.Current.LineCount-1;
+ notEndOfFolds = foldsEnum.MoveNext();
}
- //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}");
- return foldedLines;
+ return linesToSkip;
} finally {
doc.ExitReadLock ();
}
}
protected override int getAbsoluteLineIndexFromVisualLineMove (int startLine, int visualLineDiff) {
- int newVl = Math.Min (Math.Max (0, getVisualLine (startLine) + visualLineDiff), visualLineCount - 1);
- return newVl + countFoldedLinesUntil (newVl);
+ int newVl = Math.Min (Math.Max (0, getVisualLineFromAboluteLine (startLine) + visualLineDiff), visualLineCount - 1);
+ return getAbsoluteLineFromVisualLine (newVl);
}
protected override int visualLineCount
get {
if (!(Document is SourceDocument doc))
return base.visualLineCount;
- return Document.LinesCount - countFoldedLinesUntil (Document.LinesCount);
+
+ return Document.LinesCount - doc.Root.FoldedLineCount;
}
}
- protected override int visualCurrentLine => CurrentLoc.HasValue ? getVisualLine (CurrentLoc.Value.Line) : 0;
+ protected override int visualCurrentLine => CurrentLoc.HasValue ? getVisualLineFromAboluteLine (CurrentLoc.Value.Line) : 0;
protected override void updateMaxScrolls (LayoutingType layout) {
updateMargin();
Rectangle cb = ClientRectangle;
<Label Text="{../../tb.ScrollLine}" Margin="3"/>
<Label Text="HoverLine:" Foreground="Grey"/>
<Label Text="{../../tb.HoverLine}" Margin="3"/>
+ <Label Text="hoverVisualLine:" Foreground="Grey"/>
+ <Label Text="{../../tb.hoverVisualLine}" Margin="3"/>
+ <Label Text="hoverLine:" Foreground="Grey"/>
+ <Label Text="{../../tb.hoverLine}" Margin="3"/>
<Label Text="Line:" Foreground="Grey"/>
<Label Text="{../../tb.CurrentLine}" Margin="3"/>
<Label Text="Col:" Foreground="Grey"/>
using CrowEditBase;
using CrowEdit.Xml;
using System.Threading.Tasks;
+using System.Threading;
namespace CECrowPlugin
{
public ImlSyntaxAnalyser (ImlDocument document) : base (document) {}
- public override async Task<SyntaxRootNode> Process () {
+ public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
return await base.Process();
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
+using System.Threading;
using System.Threading.Tasks;
using CrowEdit.Xml;
using CrowEditBase;
MemberListSyntax processNode(MemberListSyntax memberList) {
memberList.AddChild(new SingleTokenSyntax(Read()));
while (skipTriviaAndComments(memberList)) {
+ if (cancel.IsCancellationRequested)
+ break;
+
if (Peek().Is(StyleTokenType.Name)) {
memberList.AddChild(processNode(new MemberSyntax(new MemberIdentifierSyntax(Read()))));
continue;
ImlValueSyntax processNode(ImlValueSyntax iml) {
if (accept(iml, StyleTokenType.MemberValueOpen)) {
while (tryPeek(out Token tok)) {
+ if (cancel.IsCancellationRequested)
+ break;
if (tok.Is(StyleTokenType.ConstantRefOpen)) {
iml.AddChild(processNode(new ConstanteReferenceSyntax()));
} else if (tok.Is(StyleTokenType.MemberValueClose)) {
accept(cst, StyleTokenType.ClosingBrace);
return cst;
}
-
- public override async Task<SyntaxRootNode> Process () {
+ CancellationToken cancel;
+ public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
Tokenizer tokenizer = new StyleTokenizer();
ReadOnlyTextBuffer buff = document.ImmutableBufferCopy;
Token[] tokens = tokenizer.Tokenize(buff.Source.Span);
tokIdx = 0;
+ this.cancel = cancel;
Root = new StyleRootSyntax (buff, tokens);
while (!EOF) {
+ if (cancel.IsCancellationRequested)
+ break;
if (!skipTriviaAndComments(Root))
break;
if (!Peek().Is(StyleTokenType.Name)) {
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using CrowEditBase;
//NCName | StringLiteral | CharCode | CharClass | '(' Choice ')'
// StringLiteral ::= '"' [^"]* '"' | "'" [^']* "'"
- public override async Task<SyntaxRootNode> Process()
+ public override async Task<SyntaxRootNode> Process(CancellationToken cancel = default)
{
Tokenizer tokenizer = new EbnfTokenizer();
ReadOnlyTextBuffer buff = document.ImmutableBufferCopy;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static CrowEditBase.CrowEditBase;
+using System.Threading;
namespace CERoslynPlugin
parse();
}
protected override void parse()
- {
- tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (source.ToString(), CSharpParseOptions.Default);
+ {
+ tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (source.ToString(), CSharpParseOptions.Default, "", null);
base.parse();
}
}
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using Crow.Text;
using CrowEditBase;
csdoc = document;
}
- public override async Task<SyntaxRootNode> Process () {
+ 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);
- CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge(new CSRootSyntax (buff));
-
- bridge.Visit(await csdoc.tree.GetRootAsync());
+ if (cancel.IsCancellationRequested)
+ return null;
+
+ bridge.Visit(csroot);
bridge.Root.SetTokens (bridge.Toks.ToArray());
Root = bridge.Root;
return Root;
}
}
- class CsharpSyntaxWalkerBridge : Microsoft.CodeAnalysis.CSharp.CSharpSyntaxWalker
+ class CsharpSyntaxWalkerBridge : CSharpSyntaxWalker
{
public CSRootSyntax Root;
public List<Token> Toks;
MultiNodeSyntax currentNode;
- public CsharpSyntaxWalkerBridge (CSRootSyntax root) : base (SyntaxWalkerDepth.StructuredTrivia)
+ 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);
public override void VisitToken (SyntaxToken token)
{
+ if (cancel.IsCancellationRequested)
+ return;
+
VisitLeadingTrivia (token);
Microsoft.CodeAnalysis.Text.TextSpan fs = token.Span;
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) {
startOfTok = 0;
while(!reader.EndOfSpan) {
+ if (cancel.IsCancellationRequested)
+ return;
switch (reader.Peek) {
case '\x85':
case '\x2028':
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
+using System.Threading;
using System.Threading.Tasks;
using CrowEditBase;
public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
//attrib.valueTok = tokIdx - attrib.TokenIndexBase;
}
- public override async Task<SyntaxRootNode> Process () {
+ public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
Tokenizer tokenizer = new XmlTokenizer();
ReadOnlyTextBuffer buff = document.ImmutableBufferCopy;
Token[] tokens = tokenizer.Tokenize(buff.Source.Span);