#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.8 KiB

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Boo.Lang.Compiler.Ast;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
namespace Grunwald.BooBinding.CodeCompletion
{
public class BooAdvancedHighlighter : AsynchronousAdvancedHighlighter
{
volatile Dictionary<int, List<int>> declarations;
public override void Initialize(TextEditorControl textEditor)
{
this.ImmediateMarkLimit = 0; // never immediately mark lines
base.Initialize(textEditor);
ParserService.ParserUpdateStepFinished += OnUpdateStep;
}
public override void Dispose()
{
ParserService.ParserUpdateStepFinished -= OnUpdateStep;
base.Dispose();
}
private class FindAssignmentsVisitor : DepthFirstVisitor
{
public Dictionary<int, List<int>> declarations = new Dictionary<int, List<int>>();
// Possible declarations:
// Dictionary<LineNumber, List<ColumnNumber>>
// LineNumber and ColumnNumber are 0-based (text editor coordinates)
public override void OnBinaryExpression(BinaryExpression node)
{
ReferenceExpression reference = node.Left as ReferenceExpression;
if (node.Operator == BinaryOperatorType.Assign
&& reference != null
&& !(reference is MemberReferenceExpression)
&& reference.LexicalInfo.IsValid)
{
int lineNumber = reference.LexicalInfo.Line - 1;
List<int> l;
if (!declarations.TryGetValue(lineNumber, out l)) {
l = new List<int>();
declarations.Add(lineNumber, l);
}
l.Add(reference.LexicalInfo.Column - 1);
}
base.OnBinaryExpression(node);
}
protected override void OnError(Node node, Exception error)
{
MessageService.ShowException(error, "VariableLookupVisitor: error processing " + node);
}
}
void OnUpdateStep(object sender, ParserUpdateStepEventArgs e)
{
if (FileUtility.IsEqualFileName(e.FileName, this.TextEditor.FileName)) {
ParseInformation parseInfo = e.ParseInformation;
if (parseInfo == null && this.declarations == null)
parseInfo = ParserService.GetParseInformation(this.TextEditor.FileName);
if (parseInfo != null) {
ICompilationUnit cu = parseInfo.CompilationUnit;
CompileUnit booCu = cu.Tag as CompileUnit;
if (booCu != null) {
FindAssignmentsVisitor visitor = new FindAssignmentsVisitor();
booCu.Accept(visitor);
this.declarations = visitor.declarations; // volatile access!
}
}
WorkbenchSingleton.SafeThreadAsyncCall(MarkOutstanding);
}
}
bool markingOutstanding;
int resolveCount;
protected override void MarkOutstanding()
{
#if DEBUG
int time = Environment.TickCount;
#endif
markingOutstanding = true;
resolveCount = 0;
base.MarkOutstanding();
markingOutstanding = false;
#if DEBUG
time = Environment.TickCount - time;
if (time > 0) {
LoggingService.Info("BooHighlighter took " + time + "ms for " + resolveCount + " resolves");
}
#endif
this.Document.CommitUpdate();
}
protected override void MarkWords(int lineNumber, LineSegment currentLine, List<TextWord> words)
{
Dictionary<int, List<int>> decl = this.declarations; // volatile access!
if (decl == null) return;
int currentLineOffset = currentLine.Offset;
List<int> list;
bool changedLine = false;
if (decl.TryGetValue(lineNumber, out list)) {
foreach (TextWord word in words) {
if (word.Type == TextWordType.Word) {
for (int i = 0; i < list.Count; i++) {
if (word.Offset == list[i]) {
LocalResolveResult rr;
resolveCount++;
rr = ParserService.Resolve(new ExpressionResult(word.Word),
lineNumber + 1, word.Offset + 1,
this.TextEditor.FileName,
this.Document.TextContent
) as LocalResolveResult;
if (rr != null
&& rr.VariableDefinitionRegion.BeginLine == lineNumber + 1
&& rr.VariableDefinitionRegion.BeginColumn == word.Offset + 1)
{
changedLine = true;
word.SyntaxColor = this.Document.HighlightingStrategy.GetColorFor("LocalVariableCreation");
} else {
list.RemoveAt(i--);
}
}
}
}
}
}
if (markingOutstanding && changedLine) {
this.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber));
}
}
}
}