private void UpdateLineCache( UserLine line ) { line.CachedLines = new List<CachedLine>(); line.CachedWrapAt = CharsPerLine; int len = 0; CachedLine cachedLine = null; foreach( var origSpan in line.Spans ) { if( cachedLine == null ) { cachedLine = new CachedLine( line ); line.CachedLines.Add( cachedLine ); } if( (origSpan.Text.Length + len) < CharsPerLine ) { cachedLine.Spans.Add( origSpan ); len += origSpan.Text.Length; } else { string spanText = origSpan.Text; while( spanText.Length > 0 ) { string substring = spanText.Substring( 0, Math.Min( CharsPerLine - len, spanText.Length ) ); spanText = spanText.Substring( Math.Min( CharsPerLine - len, spanText.Length ) ); len = 0; var cachedSpan = new Span( substring, origSpan.ForegroundColour, origSpan.BackgroundColour ); cachedLine.Spans.Add( cachedSpan ); if( spanText.Length > 0 ) { cachedLine = new CachedLine( line ); line.CachedLines.Add( cachedLine ); cachedLine.Spans.Add( line.IsOutput ? PromptOutputWrap : PromptWrap ); len += line.IsOutput ? PromptOutputWrap.Text.Length : PromptWrap.Text.Length; } } } } }
HighlightedLine DoHighlightLine(int lineNumber, IDocumentLine documentLine, CachedLine cachedLine, ITextSourceVersion newVersion) { if (parseInfo == null) { if (forceParseOnNextRefresh) { forceParseOnNextRefresh = false; parseInfo = SD.ParserService.Parse(FileName.Create(document.FileName), document) as CSharpFullParseInformation; } else { parseInfo = SD.ParserService.GetCachedParseInformation(FileName.Create(document.FileName), newVersion) as CSharpFullParseInformation; } } if (parseInfo == null) { if (invalidLines != null && !invalidLines.Contains(documentLine)) { invalidLines.Add(documentLine); //Debug.WriteLine("Semantic highlighting for line {0} - marking as invalid", lineNumber); } if (cachedLine != null) { // If there's a cached version, adjust it to the latest document changes and return it. // This avoids flickering when changing a line that contains semantic highlighting. cachedLine.Update(newVersion); #if DEBUG cachedLine.HighlightedLine.ValidateInvariants(); #endif return cachedLine.HighlightedLine; } else { return null; } } if (visitor.Resolver == null) { var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName); visitor.Resolver = parseInfo.GetResolver(compilation); } line = new HighlightedLine(document, documentLine); this.lineNumber = lineNumber; visitor.UpdateLineInformation(lineNumber); if (Debugger.IsAttached) { parseInfo.SyntaxTree.AcceptVisitor(visitor); #if DEBUG line.ValidateInvariants(); #endif } else { try { parseInfo.SyntaxTree.AcceptVisitor(visitor); #if DEBUG line.ValidateInvariants(); #endif } catch (Exception ex) { hasCrashed = true; throw new ApplicationException("Error highlighting line " + lineNumber, ex); } } //Debug.WriteLine("Semantic highlighting for line {0} - added {1} sections", lineNumber, line.Sections.Count); if (cachedLines != null && document.Version != null) { cachedLines.Add(new CachedLine(line, document.Version)); } return line; }