private void BuildModelDoWork(object sender, DoWorkEventArgs e) { if (disableEntityParsing) { return; } System.Diagnostics.Trace.WriteLine("-->> XSharpClassifier.BuildModelDoWork()"); // Note this runs in the background // parse for positional keywords that change the colors // and get a reference to the tokenstream // do we need to create a new tree // this happens the first time in the buffer only var snapshot = _buffer.CurrentSnapshot; ITokenStream tokens = null; ParseResult info; { Debug("Starting parse at {0}, version {1}", DateTime.Now, snapshot.Version.ToString()); var lines = new List <String>(); foreach (var line in snapshot.Lines) { lines.Add(line.GetText()); } info = _sourceWalker.Parse(lines, false); lock (gate) { _info = info; } Debug("Ending parse at {0}, version {1}", DateTime.Now, snapshot.Version.ToString()); } tokens = _tokens; if (info != null && tokens != null) { Debug("Starting model build at {0}, version {1}", DateTime.Now, snapshot.Version.ToString()); _sourceWalker.BuildModel(info); var regionTags = BuildRegionTags(info, snapshot, xsharpRegionStart, xsharpRegionStop); lock (gate) { _parserRegions = regionTags.ToArray(); } DoRepaintRegions(); Debug("Ending model build at {0}, version {1}", DateTime.Now, snapshot.Version.ToString()); } System.Diagnostics.Trace.WriteLine("<<-- XSharpClassifier.BuildModelDoWork()"); }
public IList <ClassificationSpan> BuildRegionTags(XSharpModel.ParseResult info, ITextSnapshot snapshot, IClassificationType start, IClassificationType stop) { if (disableRegions) { return(new List <ClassificationSpan>()); } System.Diagnostics.Trace.WriteLine("-->> XSharpClassifier.BuildRegionTags()"); var regions = new List <ClassificationSpan>(); var classList = new List <EntityObject>(); var propertyList = new List <EntityObject>(); if (info != null && snapshot != null) { // walk list of entities foreach (var oElement in info.Entities) { if (oElement.eType.NeedsEndKeyword()) { classList.Add(oElement); } if (oElement.eType == EntityType._Property) { if (oElement.oParent?.eType != EntityType._Interface) { // make sure we only push multi line properties var text = snapshot.GetLineFromPosition(oElement.nOffSet).GetText(); var substatements = text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); var words = substatements[0].Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); var singleLine = false; foreach (var word in words) { switch (word.ToLower()) { case "auto": case "get": case "set": singleLine = true; break; default: break; } } if (!singleLine) { propertyList.Add(oElement); } } } //else if (oElement.eType == EntityType._Property) //{ // classStack.Push(oElement); //} else if (oElement.eType.HasBody() || oElement.eType == EntityType._VOStruct || oElement.eType == EntityType._Union) { int nStart, nEnd; nStart = oElement.nOffSet; nEnd = oElement.nOffSet; var oNext = oElement.oNext; if (oElement.eType == EntityType._VOStruct || oElement.eType == EntityType._Union) { while (oNext != null && oNext.eType == EntityType._Field) { oNext = oNext.oNext; } } if (oNext != null) { var nLine = oNext.nStartLine; // our lines are 1 based and we want the line before, so -2 nEnd = snapshot.GetLineFromLineNumber(nLine - 2).Start; } else { if (oElement.oParent?.cName != XElement.GlobalName) { // find the endclass line after this element foreach (var oLine in info.SpecialLines) { if (oLine.eType == LineType.EndClass && oLine.Line > oElement.nStartLine) { var nLine = oLine.Line; // our lines are 1 based and we want the line before, so -2 nEnd = snapshot.GetLineFromLineNumber(nLine - 2).Start; break; } } } if (nEnd == nStart) { var nEndLine = snapshot.LineCount; // walk the special lines collection to see if there are any 'end' lines at the end of the file for (int i = info.SpecialLines.Count - 1; i >= 0; i--) { var oLine = info.SpecialLines[i]; switch (oLine.eType) { case LineType.EndNamespace: case LineType.EndClass: nEndLine = oLine.Line - 1; break; default: i = -1; // exit the loop break; } } // Our lines are 1 based, so subtract 1 nEnd = snapshot.GetLineFromLineNumber(nEndLine - 1).Start; } } if (nEnd > snapshot.Length) { nEnd = snapshot.Length; } AddRegionSpan(regions, snapshot, nStart, nEnd); } } } var blockStack = new Stack <LineObject>(); var nsStack = new Stack <LineObject>(); foreach (var oLine in info.SpecialLines) { int nStart = 0, nEnd = 0; switch (oLine.eType) { case LineType.BeginNamespace: nsStack.Push(oLine); break; case LineType.EndNamespace: if (nsStack.Count > 0) { var nsStart = nsStack.Pop(); nStart = nsStart.OffSet; nEnd = oLine.OffSet; AddRegionSpan(regions, snapshot, nStart, nEnd); } break; case LineType.EndClass: if (classList.Count > 0) { var cls = classList[0]; classList.RemoveAt(0); nStart = cls.nOffSet; nEnd = oLine.OffSet; AddRegionSpan(regions, snapshot, nStart, nEnd); } break; case LineType.EndProperty: if (propertyList.Count > 0) { var prop = propertyList[0]; propertyList.RemoveAt(0); nStart = prop.nOffSet; nEnd = oLine.OffSet; AddRegionSpan(regions, snapshot, nStart, nEnd); } break; case LineType.TokenIn: blockStack.Push(oLine); break; case LineType.TokenInOut: if (blockStack.Count > 0) { var blStart = blockStack.Peek(); // remove previous ELSEIF but not the IF if (blStart.eType == LineType.TokenInOut) { blockStack.Pop(); //} if (blStart.cArgument == "DO" || blStart.cArgument == "SWITCH") { // no contents before the first case ; } else { nStart = blStart.OffSet; // our lines are 1 based. // we do not want to include the next case line in the block from the previous one nEnd = snapshot.GetLineFromLineNumber(oLine.Line - 2).Start; AddRegionSpan(regions, snapshot, nStart, nEnd); } } } blockStack.Push(oLine); break; case LineType.TokenOut: if (blockStack.Count > 0) { // bop back to first token of the if .. endif or do case .. endcase while (blockStack.Count > 0 && blockStack.Peek().eType == LineType.TokenInOut) { var blStart = blockStack.Pop(); nStart = blStart.OffSet; nEnd = snapshot.GetLineFromLineNumber(oLine.Line - 2).Start; AddRegionSpan(regions, snapshot, nStart, nEnd); } if (blockStack.Count > 0) { var blStart = blockStack.Pop(); nStart = blStart.OffSet; // get position of the line based on the line number nEnd = snapshot.GetLineFromLineNumber(oLine.Line - 1).Start; AddRegionSpan(regions, snapshot, nStart, nEnd); } } break; default: break; } } System.Diagnostics.Trace.WriteLine("<<-- XSharpClassifier.BuildRegionTags()"); return(regions); }