Browse Source
Boo: Assignments that introduce new local variables are highlighted. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1392 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
26 changed files with 469 additions and 136 deletions
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
// <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.TextEditor; |
||||
using ICSharpCode.TextEditor.Document; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; |
||||
|
||||
namespace Grunwald.BooBinding.CodeCompletion |
||||
{ |
||||
public class BooAdvancedHighlighter : IAdvancedHighlighter |
||||
{ |
||||
public event EventHandler MarkOutstandingRequests; |
||||
|
||||
TextEditorControl textEditor; |
||||
volatile Dictionary<int, List<int>> declarations; |
||||
|
||||
public void Initialize(TextEditorControl textEditor) |
||||
{ |
||||
LoggingService.Debug("AdvancedHighlighter created"); |
||||
this.textEditor = textEditor; |
||||
ParserService.ParserUpdateStepFinished += OnUpdateStep; |
||||
} |
||||
|
||||
public void Dispose() |
||||
{ |
||||
LoggingService.Debug("AdvancedHighlighter destroyed"); |
||||
ParserService.ParserUpdateStepFinished -= OnUpdateStep; |
||||
} |
||||
|
||||
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.ShowError(error, "VariableLookupVisitor: error processing " + node); |
||||
} |
||||
} |
||||
|
||||
void OnUpdateStep(object sender, ParserUpdateStepEventArgs e) |
||||
{ |
||||
if (FileUtility.IsEqualFileName(e.FileName, textEditor.FileName)) { |
||||
ParseInformation parseInfo = e.ParseInformation; |
||||
if (parseInfo == null && this.declarations == null) |
||||
parseInfo = ParserService.GetParseInformation(textEditor.FileName); |
||||
if (parseInfo != null) { |
||||
ICompilationUnit cu = parseInfo.MostRecentCompilationUnit; |
||||
CompileUnit booCu = cu.Tag as CompileUnit; |
||||
if (booCu != null) { |
||||
FindAssignmentsVisitor visitor = new FindAssignmentsVisitor(); |
||||
booCu.Accept(visitor); |
||||
this.declarations = visitor.declarations; // volatile access!
|
||||
} |
||||
} |
||||
WorkbenchSingleton.SafeThreadAsyncCall(this, "RaiseMarkOutstandingRequests", e); |
||||
} |
||||
} |
||||
|
||||
bool markingOutstanding; |
||||
int resolveCount; |
||||
|
||||
void RaiseMarkOutstandingRequests(EventArgs e) |
||||
{ |
||||
#if DEBUG
|
||||
int time = Environment.TickCount; |
||||
#endif
|
||||
markingOutstanding = true; |
||||
resolveCount = 0; |
||||
if (MarkOutstandingRequests != null) { |
||||
MarkOutstandingRequests(this, e); |
||||
} |
||||
markingOutstanding = false; |
||||
#if DEBUG
|
||||
if (resolveCount > 0) { |
||||
LoggingService.Debug("AdvancedHighlighter took " + (Environment.TickCount - time) + " ms for " + resolveCount + " resolves"); |
||||
} |
||||
#endif
|
||||
textEditor.Document.CommitUpdate(); |
||||
} |
||||
|
||||
public void MarkLine(IDocument document, LineSegment currentLine, List<TextWord> words) |
||||
{ |
||||
Dictionary<int, List<int>> decl = this.declarations; // volatile access!
|
||||
if (decl == null) return; |
||||
int currentLineOffset = currentLine.Offset; |
||||
int lineNumber = document.GetLineNumberForOffset(currentLineOffset); |
||||
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, |
||||
textEditor.FileName, |
||||
textEditor.Document.TextContent |
||||
) as LocalResolveResult; |
||||
if (rr != null |
||||
&& rr.Field.Region.BeginLine == lineNumber + 1 |
||||
&& rr.Field.Region.BeginColumn == word.Offset + 1) |
||||
{ |
||||
changedLine = true; |
||||
word.SyntaxColor = textEditor.Document.HighlightingStrategy.GetColorFor("LocalVariableCreation"); |
||||
} else { |
||||
list.RemoveAt(i--); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (markingOutstanding && changedLine) { |
||||
textEditor.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
// <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.IO; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace Grunwald.BooBinding.CodeCompletion |
||||
{ |
||||
public class BooRefactoringProvider : RefactoringProvider |
||||
{ |
||||
public static readonly BooRefactoringProvider BooProvider = new BooRefactoringProvider(); |
||||
|
||||
public override bool IsEnabledForFile(string fileName) |
||||
{ |
||||
return ".boo".Equals(Path.GetExtension(fileName), StringComparison.InvariantCultureIgnoreCase); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
// <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 System.Drawing; |
||||
using System.IO; |
||||
using System.Xml; |
||||
using System.Windows.Forms; |
||||
using ICSharpCode.TextEditor; |
||||
using ICSharpCode.TextEditor.Document; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor |
||||
{ |
||||
public interface IAdvancedHighlighter : IDisposable |
||||
{ |
||||
/// <summary>
|
||||
/// Is called once after creating the highlighter. Gives your highlighter a chance
|
||||
/// to register events on the text editor.
|
||||
/// </summary>
|
||||
void Initialize(TextEditorControl textEditor); |
||||
|
||||
/// <summary>
|
||||
/// Gives your highlighter the chance to change the highlighting of the words.
|
||||
/// </summary>
|
||||
void MarkLine(IDocument document, LineSegment currentLine, List<TextWord> words); |
||||
|
||||
/// <summary>
|
||||
/// When your class fires this event, MarkLine will be called for all waiting lines.
|
||||
/// You can fire this event on any thread, but MarkLine will be called on that thread
|
||||
/// - so if you use multithreading, you must invoke when accessing the document inside
|
||||
/// MarkLine.
|
||||
/// </summary>
|
||||
event EventHandler MarkOutstandingRequests; |
||||
} |
||||
|
||||
internal class ParserHighlightingStrategy : DefaultHighlightingStrategy |
||||
{ |
||||
readonly object lockObject = new object(); |
||||
readonly IAdvancedHighlighter highlighter; |
||||
IDocument document; |
||||
Dictionary<LineSegment, List<TextWord>> outstanding = new Dictionary<LineSegment, List<TextWord>>(); |
||||
|
||||
public ParserHighlightingStrategy(DefaultHighlightingStrategy baseStrategy, IAdvancedHighlighter highlighter) |
||||
{ |
||||
ImportSettingsFrom(baseStrategy); |
||||
this.highlighter = highlighter; |
||||
highlighter.MarkOutstandingRequests += OnMarkOutstandingRequest; |
||||
} |
||||
|
||||
int directMark; // counter for immediate marking when only few lines have changed
|
||||
|
||||
public override void MarkTokens(IDocument document) |
||||
{ |
||||
lock (lockObject) { |
||||
outstanding.Clear(); |
||||
} |
||||
base.MarkTokens(document); |
||||
} |
||||
|
||||
public override void MarkTokens(IDocument document, List<LineSegment> inputLines) |
||||
{ |
||||
directMark = (inputLines.Count < 3) ? inputLines.Count : 0; |
||||
base.MarkTokens(document, inputLines); |
||||
directMark = 0; |
||||
} |
||||
|
||||
protected override void OnParsedLine(IDocument document, LineSegment currentLine, List<TextWord> words) |
||||
{ |
||||
int ln = currentLineNumber; |
||||
|
||||
if (directMark > 0) { |
||||
directMark--; |
||||
highlighter.MarkLine(document, currentLine, words); |
||||
} else { |
||||
this.document = document; |
||||
lock (lockObject) { |
||||
outstanding[currentLine] = words; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void OnMarkOutstandingRequest(object sender, EventArgs e) |
||||
{ |
||||
Dictionary<LineSegment, List<TextWord>> oldOutstanding; |
||||
lock (lockObject) { |
||||
oldOutstanding = outstanding; |
||||
outstanding = new Dictionary<LineSegment, List<TextWord>>(); |
||||
} |
||||
// We cannot call MarkLine inside lock(lockObject) because then the main
|
||||
// thread could deadlock with the highlighter thread.
|
||||
foreach (KeyValuePair<LineSegment, List<TextWord>> pair in oldOutstanding) { |
||||
highlighter.MarkLine(document, pair.Key, pair.Value); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue