From c89b7a5e298c041383f4eeea495ab45dd2669483 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 31 Jul 2010 10:02:26 +0000 Subject: [PATCH] implemented SD-631 for VB .NET git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6329 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/CSharpCompletionBinding.cs | 5 +- .../Project/Src/VBNetCompletionBinding.cs | 31 +++++++++- .../Src/Lexer/VBNet/ExpressionFinder.atg | 2 +- .../Src/Lexer/VBNet/ExpressionFinder.cs | 4 ++ .../Project/Src/Lexer/VBNet/Parser.cs | 3 + .../Project/Src/Lexer/VBNet/PushParser.frame | 1 + .../CodeCompletion/CodeCompletionBinding.cs | 4 +- .../CodeCompletion/IInsightWindowHandler.cs | 13 +--- .../CodeCompletion/MethodInsightItem.cs | 60 +++++++++++++++++-- .../CodeCompletion/MethodInsightProvider.cs | 1 + .../NRefactoryInsightWindowHandler.cs | 18 ++++-- 11 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index 22238360be..4749877218 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -45,8 +45,11 @@ namespace CSharpBinding return true; }*/ } else if (ch == ',' && CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled) { - if (insightHandler.InsightRefreshOnComma(editor, ch)) + IInsightWindow insightWindow; + if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) { + insightHandler.HighlightParameter(insightWindow, -1); // disable highlighting return CodeCompletionKeyPressResult.Completed; + } } else if(ch == '=') { var curLine = editor.Document.GetLineForOffset(cursor); string documentText = editor.Document.Text; diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs index 8c1cab6dbb..30ac6888a8 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetCompletionBinding.cs @@ -63,14 +63,24 @@ namespace ICSharpCode.VBNetBinding case '(': if (CodeCompletionOptions.InsightEnabled) { IInsightWindow insightWindow = editor.ShowInsightWindow(new MethodInsightProvider().ProvideInsight(editor)); - if (insightWindow != null) + if (insightWindow != null) { insightHandler.InitializeOpenedInsightWindow(editor, insightWindow); + insightHandler.HighlightParameter(insightWindow, 0); + } return CodeCompletionKeyPressResult.Completed; } break; case ',': - if (CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled && insightHandler.InsightRefreshOnComma(editor, ch)) - return CodeCompletionKeyPressResult.Completed; + if (CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled) { + IInsightWindow insightWindow; + editor.Document.Insert(editor.Caret.Offset, ","); + if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) { + if (insightWindow != null) { + insightHandler.HighlightParameter(insightWindow, GetArgumentIndex(editor) + 1); + } + return CodeCompletionKeyPressResult.EatKey; + } + } break; case '\n': TryDeclarationTypeInference(editor, editor.Document.GetLineForOffset(editor.Caret.Offset)); @@ -126,6 +136,21 @@ namespace ICSharpCode.VBNetBinding return CodeCompletionKeyPressResult.None; } + static int GetArgumentIndex(ITextEditor editor) + { + ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, editor.Document.CreateReader()); + ExpressionFinder ef = new ExpressionFinder(); + + Token t = lexer.NextToken(); + + while (t.Kind != Tokens.EOF && t.EndLocation < editor.Caret.Position) { + ef.InformToken(t); + t = lexer.NextToken(); + } + + return ef.ActiveArgument; + } + bool IsTypeCharacter(char ch, char prevChar) { ch = char.ToUpperInvariant(ch); diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg index 7e42fef68a..4757115a05 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg @@ -1182,7 +1182,7 @@ InvocationStatement = . ArgumentList = - Expression { "," [ Expression ] } + (. activeArgument = 0; .) Expression { "," (. activeArgument++; .) [ Expression ] } | "," [ Expression ] { "," [ Expression ] } . diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs index 1f5535adfe..fa51770a36 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs @@ -129,6 +129,10 @@ namespace ICSharpCode.NRefactory.Parser.VB get { return isMissingModifier; } } + public int ActiveArgument { + get { return activeArgument; } + } + public List Errors { get { return errors; } } diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs index 2ce197700f..0ad128349e 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs @@ -1440,6 +1440,7 @@ partial class ExpressionFinder { bool identifierExpected = false; bool nextTokenIsStartOfImportsOrAccessExpression = false; bool isMissingModifier = false; + int activeArgument = 0; List errors = new List(); public ExpressionFinder() @@ -1859,6 +1860,7 @@ partial class ExpressionFinder { case 44: { if (la == null) { currentState = 44; break; } if (set[22].Get(la.kind)) { + activeArgument = 0; goto case 418; } else { if (la.kind == 22) { @@ -5639,6 +5641,7 @@ partial class ExpressionFinder { } } case 420: { + activeArgument++; nextTokenIsPotentialStartOfExpression = true; goto case 421; } diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame index cc50ca8cf5..8ab5b75b4e 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame @@ -40,6 +40,7 @@ partial class ExpressionFinder { bool identifierExpected = false; bool nextTokenIsStartOfImportsOrAccessExpression = false; bool isMissingModifier = false; + int activeArgument = 0; List errors = new List(); public ExpressionFinder() diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs index 005288a28a..f95de9a154 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs @@ -175,8 +175,10 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion case '(': if (enableMethodInsight && CodeCompletionOptions.InsightEnabled) { IInsightWindow insightWindow = editor.ShowInsightWindow(new MethodInsightProvider().ProvideInsight(editor)); - if (insightWindow != null) + if (insightWindow != null) { insightHandler.InitializeOpenedInsightWindow(editor, insightWindow); + insightHandler.HighlightParameter(insightWindow, -1); // disable highlighting + } return CodeCompletionKeyPressResult.Completed; } break; diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs index b4b66f0aab..649a9d897a 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs @@ -6,22 +6,13 @@ // using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.Parser; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; -using CSTokens = ICSharpCode.NRefactory.Parser.CSharp.Tokens; -using VBTokens = ICSharpCode.NRefactory.Parser.VB.Tokens; namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion { public interface IInsightWindowHandler { void InitializeOpenedInsightWindow(ITextEditor editor, IInsightWindow insightWindow); - bool InsightRefreshOnComma(ITextEditor editor, char ch); + bool InsightRefreshOnComma(ITextEditor editor, char ch, out IInsightWindow insightWindow); + void HighlightParameter(IInsightWindow window, int index); } } diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs index 09040d2ca9..130f5b4eba 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs @@ -5,6 +5,8 @@ // $Revision$ // +using System.Windows.Controls; +using System.Windows.Documents; using ICSharpCode.SharpDevelop.Dom; using System; @@ -22,6 +24,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion if (entity == null) throw new ArgumentNullException("entity"); this.entity = entity; + this.highlightParameter = -1; } public IEntity Entity { @@ -31,15 +34,60 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion string headerText; bool descriptionCreated; string description; + int highlightParameter; + object fancyHeader; - public object Header { - get { - if (headerText == null) { - IAmbience ambience = AmbienceService.GetCurrentAmbience(); - ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; - headerText = ambience.Convert(entity); + public int HighlightParameter { + get { return highlightParameter; } + set { + if (highlightParameter != value) { + highlightParameter = value; + fancyHeader = GenerateHeader(); } + } + } + + object GenerateHeader() + { + IAmbience ambience = AmbienceService.GetCurrentAmbience(); + ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; + + if (headerText == null) { + headerText = ambience.Convert(entity); + } + + if (highlightParameter < 0) return headerText; + + if (entity is IMethod) { + var method = entity as IMethod; + string param = ""; + if (method.Parameters.Count > highlightParameter) + param = ambience.Convert(method.Parameters[highlightParameter]); + + if (!string.IsNullOrEmpty(param)) { + string[] parts = headerText.Split(new[] { param }, StringSplitOptions.None); + if (parts.Length != 2) + return headerText; + return new Span() { + Inlines = { + parts[0], + new Bold() { Inlines = { param } }, + parts[1] + } + }; + } + } + + return headerText; + } + + public object Header { + get { + if (fancyHeader == null) + fancyHeader = GenerateHeader(); + + return fancyHeader; } } diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs index 51964a3140..c5f33214ac 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs @@ -124,6 +124,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion // method as normal - this is required to show the list of // parameters the method expects. m.IsExtensionMethod = false; + m.Modifiers ^= ModifierEnum.Static; m.Parameters.RemoveAt(0); methods.Add(m); } diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/NRefactoryInsightWindowHandler.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/NRefactoryInsightWindowHandler.cs index b06e421675..16d16f8cf4 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/NRefactoryInsightWindowHandler.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/NRefactoryInsightWindowHandler.cs @@ -143,7 +143,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion return rr; } - public bool InsightRefreshOnComma(ITextEditor editor, char ch) + public bool InsightRefreshOnComma(ITextEditor editor, char ch, out IInsightWindow insightWindow) { // Show MethodInsightWindow or IndexerInsightWindow NRefactoryResolver r = new NRefactoryResolver(languageProperties); @@ -170,7 +170,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion if (c == '(' || c == '[') { var insightProvider = new MethodInsightProvider { LookupOffset = offset }; var insightItems = insightProvider.ProvideInsight(editor); - ShowInsight(editor, insightItems, ResolveCallParameters(editor, call), ch); + insightWindow = ShowInsight(editor, insightItems, ResolveCallParameters(editor, call), ch); return true; } else { Core.LoggingService.Warn("Expected '(' or '[' at start position"); @@ -178,6 +178,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion } } } + insightWindow = null; return false; } @@ -191,11 +192,11 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion } } - void ShowInsight(ITextEditor editor, IList insightItems, ICollection parameters, char charTyped) + IInsightWindow ShowInsight(ITextEditor editor, IList insightItems, ICollection parameters, char charTyped) { int paramCount = parameters.Count; if (insightItems == null || insightItems.Count == 0) - return; + return null; bool overloadIsSure; int defaultIndex; if (insightItems.Count == 1) { @@ -226,6 +227,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion ProvideContextCompletion(editor, param.ReturnType, charTyped); } } + return insightWindow; } // TODO : remove this code duplication! @@ -274,5 +276,13 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion return base.ProcessInput(key); } } + + public void HighlightParameter(IInsightWindow window, int index) + { + var item = window.SelectedItem as MethodInsightItem; + + if (item != null) + item.HighlightParameter = index; + } } }