From a3b4fd03016b35b010d46e421dc7861d8a88bc32 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 6 May 2006 19:49:53 +0000 Subject: [PATCH] Added support for advanced syntax highlighters. Boo: Assignments that introduce new local variables are highlighted. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1392 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/AddIns/BackendBindings/Boo/BooBinding.sln | 4 +- .../Boo/BooBinding/Project/BooBinding.addin | 4 + .../Boo/BooBinding/Project/BooBinding.csproj | 4 +- .../Project/Src/BooLanguageProperties.cs | 6 + .../CodeCompletion/BooAdvancedHighlighter.cs | 155 ++++++++++++++++++ .../Project/Src/CodeCompletion/BooParser.cs | 2 +- .../CodeCompletion/BooRefactoringProvider.cs | 23 +++ .../Src/CodeCompletion/ConvertVisitor.cs | 1 + .../CodeCompletion/VariableLookupVisitor.cs | 2 +- .../Misc/CodeAnalysis/CodeAnalysis.addin | 3 +- .../Project/Src/Nodes/EnvironmentNode.cs | 18 +- .../Project/Resources/Boo.xshd | 1 + .../Project/Resources/Mode.xsd | 101 +++--------- .../DefaultHighlightingStrategy.cs | 40 +++-- .../HighlightingDefinitionParser.cs | 24 +-- .../Project/Src/Gui/TextEditorControlBase.cs | 9 +- .../Project/ICSharpCode.SharpDevelop.csproj | 3 +- .../ParseInformationEventHandler.cs | 10 +- .../Services/ParserService/ParserService.cs | 2 +- .../NRefactoryRefactoringProvider.cs | 11 ++ .../RefactoringService/RefactorMenu.cs | 15 +- .../RefactoringService/RefactoringProvider.cs | 14 +- .../Commands/TextAreaContextmenuCommands.cs | 3 + .../Gui/Editor/ParserHighlightingStrategy.cs | 101 ++++++++++++ .../Gui/Editor/SharpDevelopTextAreaControl.cs | 46 ++++-- .../Gui/Editor/TextEditorDisplayBinding.cs | 3 + 26 files changed, 469 insertions(+), 136 deletions(-) create mode 100644 src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooAdvancedHighlighter.cs create mode 100644 src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooRefactoringProvider.cs create mode 100644 src/Main/Base/Project/Src/TextEditor/Gui/Editor/ParserHighlightingStrategy.cs diff --git a/src/AddIns/BackendBindings/Boo/BooBinding.sln b/src/AddIns/BackendBindings/Boo/BooBinding.sln index 02bc32ff2a..0fdac416d0 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding.sln +++ b/src/AddIns/BackendBindings/Boo/BooBinding.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 9.00 -# SharpDevelop 2.1.0.1333 +# SharpDevelop 2.1.0.1388 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter", "NRefactoryToBooConverter\Project\NRefactoryToBooConverter.csproj", "{DBCF20A1-BA13-4582-BFA9-74DE4D987B73}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter.Tests", "NRefactoryToBooConverter\Test\NRefactoryToBooConverter.Tests.csproj", "{C9DE556D-325C-4544-B29F-16A9EB7C9830}" @@ -22,6 +22,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "..\..\Disp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding.Tests", "BooBinding\Test\BooBinding.Tests.csproj", "{6FA16499-896F-4C02-BB43-1AF5C6C7C713}" EndProject +Project("{A33008B1-5DAC-44D5-9060-242E3B6E38F2}") = "Boo.InterpreterAddIn", "Boo.InterpreterAddIn\Project\Boo.InterpreterAddIn.booproj", "{928E34B2-5E46-4A4D-8E4D-2CA2CCDB905A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin index b01e9fb297..2f8b51ce33 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin @@ -88,6 +88,10 @@ + + + + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj index 3146967f52..0da5b62f2a 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj @@ -89,6 +89,8 @@ Always + + @@ -150,4 +152,4 @@ - + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageProperties.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageProperties.cs index 6a1958becc..c4ff6b34c5 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageProperties.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageProperties.cs @@ -45,5 +45,11 @@ namespace Grunwald.BooBinding return true; } } + + public override ICSharpCode.SharpDevelop.Refactoring.RefactoringProvider RefactoringProvider { + get { + return CodeCompletion.BooRefactoringProvider.BooProvider; + } + } } } diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooAdvancedHighlighter.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooAdvancedHighlighter.cs new file mode 100644 index 0000000000..386bda55cf --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooAdvancedHighlighter.cs @@ -0,0 +1,155 @@ +// +// +// +// +// $Revision$ +// + +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> 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> declarations = new Dictionary>(); + // Possible declarations: + // Dictionary> + // 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 l; + if (!declarations.TryGetValue(lineNumber, out l)) { + l = new List(); + 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 words) + { + Dictionary> decl = this.declarations; // volatile access! + if (decl == null) return; + int currentLineOffset = currentLine.Offset; + int lineNumber = document.GetLineNumberForOffset(currentLineOffset); + List 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)); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs index f7f6ea63f5..5630423183 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs @@ -168,7 +168,7 @@ namespace Grunwald.BooBinding.CodeCompletion private ICompilationUnit Parse(IProjectContent projectContent, string fileName, int[] lineLength, BooCompiler compiler) { compiler.Parameters.OutputWriter = new StringWriter(); - compiler.Parameters.TraceSwitch.Level = System.Diagnostics.TraceLevel.Warning; + compiler.Parameters.TraceSwitch.Level = System.Diagnostics.TraceLevel.Off; Compile compilePipe = new Compile(); BooParsingStep parsingStep = (BooParsingStep)compilePipe[0]; diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooRefactoringProvider.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooRefactoringProvider.cs new file mode 100644 index 0000000000..a22e4bf544 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooRefactoringProvider.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision$ +// + +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); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs index 7c1dc69b91..8850fa66cf 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs @@ -40,6 +40,7 @@ namespace Grunwald.BooBinding.CodeCompletion public override void Run() { try { + _cu.Tag = CompileUnit; Visit(CompileUnit); } catch (Exception ex) { MessageService.ShowError(ex); diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs index ac78889419..b1090443fd 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs @@ -65,7 +65,7 @@ namespace Grunwald.BooBinding.CodeCompletion ReferenceExpression reference = node.Left as ReferenceExpression; if (node.Operator == BinaryOperatorType.Assign && reference != null) { if (!(reference is MemberReferenceExpression)) { - DeclarationFound(reference.Name, null, node.Right, node.LexicalInfo); + DeclarationFound(reference.Name, null, node.Right, reference.LexicalInfo); } } } diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin index 2874c6b144..6e8f0bcfd2 100644 --- a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin +++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin @@ -24,7 +24,6 @@ + class = "ICSharpCode.CodeAnalysis.CheckCurrentProjectCommand"/> diff --git a/src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/EnvironmentNode.cs b/src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/EnvironmentNode.cs index 6b1f1e600c..ab491259ce 100644 --- a/src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/EnvironmentNode.cs +++ b/src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/EnvironmentNode.cs @@ -25,6 +25,8 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes public string[] ColorDescs; public EditorHighlightColor[] Colors; + const string CustomColorPrefix = "Custom$"; + public EnvironmentNode(XmlElement el) { ArrayList envColors = new ArrayList(); @@ -33,8 +35,13 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes if (el != null) { foreach (XmlNode node in el.ChildNodes) { if (node is XmlElement) { - envColorNames.Add(node.Name); - envColorDescriptions.Add("${res:Dialog.HighlightingEditor.EnvColors." + node.Name + "}"); + if (node.Name == "Custom") { + envColorNames.Add(CustomColorPrefix + (node as XmlElement).GetAttribute("name")); + envColorDescriptions.Add((node as XmlElement).GetAttribute("name")); + } else { + envColorNames.Add(node.Name); + envColorDescriptions.Add("${res:Dialog.HighlightingEditor.EnvColors." + node.Name + "}"); + } envColors.Add(new EditorHighlightColor((XmlElement)node)); } } @@ -66,7 +73,12 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes { writer.WriteStartElement("Environment"); for (int i = 0; i < ColorNames.Length; i++) { - writer.WriteStartElement(ColorNames[i]); + if (ColorNames[i].StartsWith(CustomColorPrefix)) { + writer.WriteStartElement("Custom"); + writer.WriteAttributeString("name", ColorNames[i].Substring(CustomColorPrefix.Length)); + } else { + writer.WriteStartElement(ColorNames[i]); + } Colors[i].WriteXmlAttributes(writer); writer.WriteEndElement(); } diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Boo.xshd b/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Boo.xshd index ee793c29ba..d28d69c34d 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Boo.xshd +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Boo.xshd @@ -14,6 +14,7 @@ + diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Mode.xsd b/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Mode.xsd index 97bbeaf63e..d5a46e6027 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Mode.xsd +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Resources/Mode.xsd @@ -19,102 +19,43 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + + + + - - - + - - - + + + - + + + + + + diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/DefaultHighlightingStrategy.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/DefaultHighlightingStrategy.cs index 7833b6662f..9481c71d3f 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/DefaultHighlightingStrategy.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/DefaultHighlightingStrategy.cs @@ -24,14 +24,6 @@ namespace ICSharpCode.TextEditor.Document List rules = new List(); Dictionary environmentColors = new Dictionary(); - - public IEnumerable> EnvironmentColors { - get { - return environmentColors; - } - } - - Dictionary properties = new Dictionary(); string[] extensions; @@ -47,6 +39,23 @@ namespace ICSharpCode.TextEditor.Document } } + public IEnumerable> EnvironmentColors { + get { + return environmentColors; + } + } + + protected void ImportSettingsFrom(DefaultHighlightingStrategy source) + { + properties = source.properties; + extensions = source.extensions; + digitColor = source.digitColor; + defaultRuleSet = source.defaultRuleSet; + name = source.name; + rules = source.rules; + environmentColors = source.environmentColors; + defaultTextColor = source.defaultTextColor; + } public DefaultHighlightingStrategy() : this("Default") { @@ -249,11 +258,12 @@ namespace ICSharpCode.TextEditor.Document // Line state variable protected LineSegment currentLine; + protected int currentLineNumber; // Span stack state variable protected Stack currentSpanStack; - public void MarkTokens(IDocument document) + public virtual void MarkTokens(IDocument document) { if (Rules.Count == 0) { return; @@ -283,6 +293,7 @@ namespace ICSharpCode.TextEditor.Document return; } + currentLineNumber = lineNumber; List words = ParseLine(document); // Alex: clear old words if (currentLine.Words != null) { @@ -300,6 +311,7 @@ namespace ICSharpCode.TextEditor.Document bool MarkTokensInLine(IDocument document, int lineNumber, ref bool spanChanged) { + currentLineNumber = lineNumber; bool processNextLine = false; LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null); @@ -396,7 +408,7 @@ namespace ICSharpCode.TextEditor.Document return processNextLine; } - public void MarkTokens(IDocument document, List inputLines) + public virtual void MarkTokens(IDocument document, List inputLines) { if (Rules.Count == 0) { return; @@ -645,9 +657,15 @@ namespace ICSharpCode.TextEditor.Document PushCurWord(document, ref markNext, words); + OnParsedLine(document, currentLine, words); + return words; } - + + protected virtual void OnParsedLine(IDocument document, LineSegment currentLine, List words) + { + } + protected virtual bool OverrideSpan(string spanBegin, IDocument document, List words, Span span, ref int lineOffset) { return false; diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionParser.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionParser.cs index f3ccc67416..1bec383cca 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionParser.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionParser.cs @@ -21,16 +21,16 @@ namespace ICSharpCode.TextEditor.Document { static ArrayList errors = null; - public static DefaultHighlightingStrategy Parse(SyntaxMode syntaxMode, XmlTextReader xmlTextReader) + public static DefaultHighlightingStrategy Parse(SyntaxMode syntaxMode, XmlReader xmlReader) { - return Parse(null, syntaxMode, xmlTextReader); + return Parse(null, syntaxMode, xmlReader); } - public static DefaultHighlightingStrategy Parse(DefaultHighlightingStrategy highlighter, SyntaxMode syntaxMode, XmlTextReader xmlTextReader) + public static DefaultHighlightingStrategy Parse(DefaultHighlightingStrategy highlighter, SyntaxMode syntaxMode, XmlReader xmlReader) { if (syntaxMode == null) throw new ArgumentNullException("syntaxMode"); - if (xmlTextReader == null) + if (xmlReader == null) throw new ArgumentNullException("xmlTextReader"); try { XmlReaderSettings settings = new XmlReaderSettings(); @@ -38,13 +38,13 @@ namespace ICSharpCode.TextEditor.Document settings.Schemas.Add("", new XmlTextReader(shemaStream)); settings.Schemas.ValidationEventHandler += new ValidationEventHandler(ValidationHandler); settings.ValidationType = ValidationType.Schema; - XmlReader validatingReader = XmlReader.Create(xmlTextReader, settings); + XmlReader validatingReader = XmlReader.Create(xmlReader, settings); // XmlValidatingReader validatingReader = new XmlValidatingReader(xmlTextReader); // Stream shemaStream = Assembly.GetCallingAssembly().GetManifestResourceStream("Resources.Mode.xsd"); // validatingReader.Schemas.Add("", new XmlTextReader(shemaStream)); // validatingReader.ValidationType = ValidationType.Schema; - + XmlDocument doc = new XmlDocument(); doc.Load(validatingReader); @@ -70,7 +70,11 @@ namespace ICSharpCode.TextEditor.Document foreach (XmlNode node in environment.ChildNodes) { if (node is XmlElement) { XmlElement el = (XmlElement)node; - highlighter.SetColorFor(el.Name, el.HasAttribute("bgcolor") ? new HighlightBackground(el) : new HighlightColor(el)); + if (el.Name == "Custom") { + highlighter.SetColorFor(el.GetAttribute("name"), el.HasAttribute("bgcolor") ? new HighlightBackground(el) : new HighlightColor(el)); + } else { + highlighter.SetColorFor(el.Name, el.HasAttribute("bgcolor") ? new HighlightBackground(el) : new HighlightColor(el)); + } } } } @@ -91,20 +95,20 @@ namespace ICSharpCode.TextEditor.Document highlighter.AddRuleSet(new HighlightRuleSet(element)); } - xmlTextReader.Close(); + xmlReader.Close(); if(errors!=null) { ReportErrors(syntaxMode.FileName); errors = null; return null; } else { - return highlighter; + return highlighter; } } catch (Exception e) { MessageBox.Show("Could not load mode definition file '" + syntaxMode.FileName + "'.\n" + e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); return null; } - } + } private static void ValidationHandler(object sender, ValidationEventArgs args) { diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs index af773287f0..acf9508146 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs @@ -499,11 +499,10 @@ namespace ICSharpCode.TextEditor protected TextEditorControlBase() { GenerateDefaultActions(); - HighlightingManager.Manager.ReloadSyntaxHighlighting += new EventHandler(ReloadHighlighting); + HighlightingManager.Manager.ReloadSyntaxHighlighting += new EventHandler(OnReloadHighlighting); } - - void ReloadHighlighting(object sender, EventArgs e) + protected virtual void OnReloadHighlighting(object sender, EventArgs e) { if (Document.HighlightingStrategy != null) { Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(Document.HighlightingStrategy.Name); @@ -511,8 +510,6 @@ namespace ICSharpCode.TextEditor } } - - internal IEditAction GetEditAction(Keys keyData) { if (!editactions.ContainsKey(keyData)) { @@ -723,7 +720,7 @@ namespace ICSharpCode.TextEditor protected override void Dispose(bool disposing) { if (disposing) { - HighlightingManager.Manager.ReloadSyntaxHighlighting -= new EventHandler(ReloadHighlighting); + HighlightingManager.Manager.ReloadSyntaxHighlighting -= new EventHandler(OnReloadHighlighting); document.HighlightingStrategy = null; document.UndoStack.TextEditorControl = null; } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index aa6cde09d9..03231ee6f9 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -769,6 +769,7 @@ + @@ -797,4 +798,4 @@ - + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventHandler.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventHandler.cs index cefea22ae1..0cb78871c1 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventHandler.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventHandler.cs @@ -59,12 +59,14 @@ namespace ICSharpCode.Core string fileName; string content; bool updated; + ParseInformation parseInformation; - public ParserUpdateStepEventArgs(string fileName, string content, bool updated) + public ParserUpdateStepEventArgs(string fileName, string content, bool updated, ParseInformation parseInformation) { this.fileName = fileName; this.content = content; this.updated = updated; + this.parseInformation = parseInformation; } public string FileName { @@ -82,5 +84,11 @@ namespace ICSharpCode.Core return updated; } } + + public ParseInformation ParseInformation { + get { + return parseInformation; + } + } } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 48309af5b9..32c5f9911e 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -344,7 +344,7 @@ namespace ICSharpCode.Core ((IParseInformationListener)editable).ParseInformationUpdated(parseInformation); } } - OnParserUpdateStepFinished(new ParserUpdateStepEventArgs(fileName, text, updated)); + OnParserUpdateStepFinished(new ParserUpdateStepEventArgs(fileName, text, updated, parseInformation)); } } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/NRefactoryRefactoringProvider.cs b/src/Main/Base/Project/Src/Services/RefactoringService/NRefactoryRefactoringProvider.cs index c06d71d22a..37db534027 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/NRefactoryRefactoringProvider.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/NRefactoryRefactoringProvider.cs @@ -19,6 +19,17 @@ namespace ICSharpCode.SharpDevelop.Refactoring { public static readonly NRefactoryRefactoringProvider NRefactoryProviderInstance = new NRefactoryRefactoringProvider(); + public override bool IsEnabledForFile(string fileName) + { + string extension = Path.GetExtension(fileName); + if (extension.Equals(".cs", StringComparison.InvariantCultureIgnoreCase)) + return true; + else if (extension.Equals(".vb", StringComparison.InvariantCultureIgnoreCase)) + return true; + else + return false; + } + #region FindUnusedUsingDeclarations protected class PossibleTypeReference { diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactorMenu.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactorMenu.cs index 8aad222230..da784d2715 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactorMenu.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactorMenu.cs @@ -37,13 +37,20 @@ namespace ICSharpCode.SharpDevelop.Refactoring return false; } ITextEditorControlProvider provider = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as ITextEditorControlProvider; - if (provider == null) return false; + if (provider == null) + return false; LanguageProperties language = ParserService.CurrentProjectContent.Language; - if (language == null) return false; + if (language == null) + return false; - string supports = condition.Properties["supports"]; - if (supports == "*") return true; RefactoringProvider rp = language.RefactoringProvider; + if (!rp.IsEnabledForFile(provider.TextEditorControl.FileName)) + return false; + + string supports = condition.Properties["supports"]; + if (supports == "*") + return true; + Type t = rp.GetType(); try { return (bool)t.InvokeMember("Supports" + supports, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, rp, null); diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringProvider.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringProvider.cs index 69f2101984..4ee2837cce 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringProvider.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringProvider.cs @@ -11,15 +11,25 @@ using ICSharpCode.SharpDevelop.Dom; namespace ICSharpCode.SharpDevelop.Refactoring { - public class RefactoringProvider + public abstract class RefactoringProvider { /// /// A RefactoringProvider instance that supports no refactorings. /// - public static readonly RefactoringProvider DummyProvider = new RefactoringProvider(); + public static readonly RefactoringProvider DummyProvider = new DummyRefactoringProvider(); protected RefactoringProvider() {} + public abstract bool IsEnabledForFile(string fileName); + + private class DummyRefactoringProvider : RefactoringProvider + { + public override bool IsEnabledForFile(string fileName) + { + return false; + } + } + public virtual bool SupportsFindUnusedUsingDeclarations { get { return false; diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/TextAreaContextmenuCommands.cs b/src/Main/Base/Project/Src/TextEditor/Commands/TextAreaContextmenuCommands.cs index a673ab29c4..153b53de0b 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/TextAreaContextmenuCommands.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/TextAreaContextmenuCommands.cs @@ -69,6 +69,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands throw new Exception("Strategy can't be null"); } control.Document.HighlightingStrategy = strat; + if (control is SharpDevelopTextAreaControl) { + ((SharpDevelopTextAreaControl)control).InitializeAdvancedHighlighter(); + } control.Refresh(); } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ParserHighlightingStrategy.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ParserHighlightingStrategy.cs new file mode 100644 index 0000000000..7005e50460 --- /dev/null +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ParserHighlightingStrategy.cs @@ -0,0 +1,101 @@ +// +// +// +// +// $Revision$ +// + +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 + { + /// + /// Is called once after creating the highlighter. Gives your highlighter a chance + /// to register events on the text editor. + /// + void Initialize(TextEditorControl textEditor); + + /// + /// Gives your highlighter the chance to change the highlighting of the words. + /// + void MarkLine(IDocument document, LineSegment currentLine, List words); + + /// + /// 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. + /// + event EventHandler MarkOutstandingRequests; + } + + internal class ParserHighlightingStrategy : DefaultHighlightingStrategy + { + readonly object lockObject = new object(); + readonly IAdvancedHighlighter highlighter; + IDocument document; + Dictionary> outstanding = new Dictionary>(); + + 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 inputLines) + { + directMark = (inputLines.Count < 3) ? inputLines.Count : 0; + base.MarkTokens(document, inputLines); + directMark = 0; + } + + protected override void OnParsedLine(IDocument document, LineSegment currentLine, List 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> oldOutstanding; + lock (lockObject) { + oldOutstanding = outstanding; + outstanding = new Dictionary>(); + } + // We cannot call MarkLine inside lock(lockObject) because then the main + // thread could deadlock with the highlighter thread. + foreach (KeyValuePair> pair in oldOutstanding) { + highlighter.MarkLine(document, pair.Key, pair.Value); + } + } + } +} diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs index 2c324f1f43..c99f90fe4a 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs @@ -6,23 +6,18 @@ // using System; -using System.IO; -using System.Collections; -using System.Drawing; -using System.Diagnostics; +using System.Collections.Generic; using System.Windows.Forms; -using ICSharpCode.TextEditor.Document; +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.DefaultEditor.Actions; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Internal.Templates; using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Actions; -using ICSharpCode.SharpDevelop.Internal.Templates; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.TextEditor.Gui.InsightWindow; +using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Gui.CompletionWindow; - -using System.Threading; +using ICSharpCode.TextEditor.Gui.InsightWindow; namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { @@ -31,9 +26,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor readonly static string contextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ContextMenu"; readonly static string editActionsPath = "/AddIns/DefaultTextEditor/EditActions"; readonly static string formatingStrategyPath = "/AddIns/DefaultTextEditor/Formatter"; + readonly static string advancedHighlighterPath = "/AddIns/DefaultTextEditor/AdvancedHighlighter"; QuickClassBrowserPanel quickClassBrowserPanel = null; ErrorDrawer errorDrawer; + IAdvancedHighlighter advancedHighlighter; public QuickClassBrowserPanel QuickClassBrowserPanel { get { @@ -99,6 +96,10 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor quickClassBrowserPanel.Dispose(); quickClassBrowserPanel = null; } + if (advancedHighlighter != null) { + advancedHighlighter.Dispose(); + advancedHighlighter = null; + } CloseCodeCompletionWindow(this, EventArgs.Empty); CloseInsightWindow(this, EventArgs.Empty); } @@ -388,6 +389,29 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor TextEditorProperties.IndentStyle = save2; } + protected override void OnReloadHighlighting(object sender, EventArgs e) + { + base.OnReloadHighlighting(sender, e); + InitializeAdvancedHighlighter(); + } + + public void InitializeAdvancedHighlighter() + { + if (advancedHighlighter != null) { + advancedHighlighter.Dispose(); + advancedHighlighter = null; + } + string highlighterPath = advancedHighlighterPath + "/" + Document.HighlightingStrategy.Name; + if (AddInTree.ExistsTreeNode(highlighterPath)) { + IList highlighter = AddInTree.BuildItems(highlighterPath, this); + if (highlighter != null && highlighter.Count > 0) { + advancedHighlighter = highlighter[0]; + Document.HighlightingStrategy = new ParserHighlightingStrategy((DefaultHighlightingStrategy)Document.HighlightingStrategy, advancedHighlighter); + advancedHighlighter.Initialize(this); + } + } + } + public void InitializeFormatter() { string formatterPath = formatingStrategyPath + "/" + Document.HighlightingStrategy.Name; diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs index aa1da73484..c65db69c3d 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -59,9 +59,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor b2.textAreaControl.Dock = DockStyle.Fill; b2.Load(fileName); b2.textAreaControl.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName); + b2.textAreaControl.InitializeAdvancedHighlighter(); b2.textAreaControl.InitializeFormatter(); b2.ForceFoldingUpdate(); b2.textAreaControl.ActivateQuickClassBrowserOnDemand(); + return b2; } @@ -71,6 +73,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor b2.textAreaControl.Document.TextContent = StringParser.Parse(content); b2.textAreaControl.Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(language); + b2.textAreaControl.InitializeAdvancedHighlighter(); b2.textAreaControl.InitializeFormatter(); b2.textAreaControl.ActivateQuickClassBrowserOnDemand(); return b2;