diff --git a/samples/CSharpCodeCompletion/CSharpCodeCompletion.csproj b/samples/CSharpCodeCompletion/CSharpCodeCompletion.csproj
index 351c176a15..50afac8c4d 100644
--- a/samples/CSharpCodeCompletion/CSharpCodeCompletion.csproj
+++ b/samples/CSharpCodeCompletion/CSharpCodeCompletion.csproj
@@ -51,6 +51,7 @@
+
MainForm.cs
@@ -62,6 +63,7 @@
+
\ No newline at end of file
diff --git a/samples/CSharpCodeCompletion/CodeCompletionData.cs b/samples/CSharpCodeCompletion/CodeCompletionData.cs
new file mode 100644
index 0000000000..aab2d15f65
--- /dev/null
+++ b/samples/CSharpCodeCompletion/CodeCompletionData.cs
@@ -0,0 +1,112 @@
+/*
+ * Erstellt mit SharpDevelop.
+ * Benutzer: grunwald
+ * Datum: 27.08.2007
+ * Zeit: 14:25
+ *
+ * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
+ */
+
+using System;
+using ICSharpCode.TextEditor.Gui.CompletionWindow;
+using ICSharpCode.SharpDevelop.Dom;
+using ICSharpCode.SharpDevelop.Dom.CSharp;
+
+namespace CSharpEditor
+{
+ ///
+ /// Represents an item in the code completion window.
+ ///
+ class CodeCompletionData : DefaultCompletionData, ICompletionData
+ {
+ IMember member;
+ IClass c;
+
+ public CodeCompletionData(IMember member)
+ : base(member.Name, null, GetMemberImageIndex(member))
+ {
+ this.member = member;
+ }
+
+ public CodeCompletionData(IClass c)
+ : base(c.Name, null, GetClassImageIndex(c))
+ {
+ this.c = c;
+ }
+
+ int overloads = 0;
+
+ public void AddOverload()
+ {
+ overloads++;
+ }
+
+ static int GetMemberImageIndex(IMember member)
+ {
+ // Missing: different icons for private/public member
+ if (member is IMethod)
+ return 1;
+ if (member is IProperty)
+ return 2;
+ if (member is IField)
+ return 3;
+ if (member is IEvent)
+ return 6;
+ return 3;
+ }
+
+ static int GetClassImageIndex(IClass c)
+ {
+ switch (c.ClassType) {
+ case ClassType.Enum:
+ return 4;
+ default:
+ return 0;
+ }
+ }
+
+ string description;
+
+ // DefaultCompletionData.Description is not virtual, but we can reimplement
+ // the interface to get the same effect as overriding.
+ string ICompletionData.Description {
+ get {
+ if (description == null) {
+ IDecoration entity = (IDecoration)member ?? c;
+ description = GetCSharpText(entity);
+ if (overloads > 1) {
+ description += " (+" + overloads + " overloads)";
+ }
+ description += Environment.NewLine + XmlDocumentationToText(entity.Documentation);
+ }
+ return description;
+ }
+ }
+
+ ///
+ /// Converts a member to text.
+ /// Returns the declaration of the member as C# code, e.g.
+ /// "public void MemberName(string parameter)"
+ ///
+ static string GetCSharpText(IDecoration entity)
+ {
+ if (entity is IMethod)
+ return CSharpAmbience.Instance.Convert(entity as IMethod);
+ if (entity is IProperty)
+ return CSharpAmbience.Instance.Convert(entity as IProperty);
+ if (entity is IEvent)
+ return CSharpAmbience.Instance.Convert(entity as IEvent);
+ if (entity is IField)
+ return CSharpAmbience.Instance.Convert(entity as IField);
+ if (entity is IClass)
+ return CSharpAmbience.Instance.Convert(entity as IClass);
+ // unknown entity:
+ return entity.ToString();
+ }
+
+ public static string XmlDocumentationToText(string xmlDoc)
+ {
+ return xmlDoc;
+ }
+ }
+}
diff --git a/samples/CSharpCodeCompletion/CodeCompletionProvider.cs b/samples/CSharpCodeCompletion/CodeCompletionProvider.cs
index 54f5a6b19e..b7c62ad7a9 100644
--- a/samples/CSharpCodeCompletion/CodeCompletionProvider.cs
+++ b/samples/CSharpCodeCompletion/CodeCompletionProvider.cs
@@ -122,6 +122,9 @@ namespace CSharpEditor
void AddCompletionData(List resultList, ArrayList completionData)
{
+ // used to store method the names for grouping overloads
+ Dictionary nameDictionary = new Dictionary();
+
// Add the completion data as returned by SharpDevelop.Dom to the
// list for the text editor
foreach (object obj in completionData) {
@@ -130,71 +133,28 @@ namespace CSharpEditor
resultList.Add(new DefaultCompletionData((string)obj, "namespace " + obj, 5));
} else if (obj is Dom.IClass) {
Dom.IClass c = (Dom.IClass)obj;
- if (c.ClassType == Dom.ClassType.Enum) {
- resultList.Add(new DefaultCompletionData(c.Name,
- GetDescription(c),
- 4));
- } else { // missing: struct, delegate etc.
- resultList.Add(new DefaultCompletionData(c.Name,
- GetDescription(c),
- 0));
- }
+ resultList.Add(new CodeCompletionData(c));
} else if (obj is Dom.IMember) {
Dom.IMember m = (Dom.IMember)obj;
if (m is Dom.IMethod && ((m as Dom.IMethod).IsConstructor)) {
// Skip constructors
continue;
}
- // TODO: Group results by name and add "(x Overloads)" to the
+ // Group results by name and add "(x Overloads)" to the
// description if there are multiple results with the same name.
- resultList.Add(new DefaultCompletionData(m.Name,
- GetDescription(m),
- GetMemberImageIndex(m)));
+
+ CodeCompletionData data;
+ if (nameDictionary.TryGetValue(m.Name, out data)) {
+ data.AddOverload();
+ } else {
+ nameDictionary[m.Name] = data = new CodeCompletionData(m);
+ resultList.Add(data);
+ }
} else {
// Current ICSharpCode.SharpDevelop.Dom should never return anything else
throw new NotSupportedException();
}
}
}
-
- ///
- /// Converts a member to text.
- /// Returns the declaration of the member as C# code, e.g.
- /// "public void MemberName(string parameter)"
- ///
- string GetDescription(Dom.IDecoration entity)
- {
- return GetCSharpText(entity) + Environment.NewLine + entity.Documentation;
- }
-
- string GetCSharpText(Dom.IDecoration entity)
- {
- if (entity is Dom.IMethod)
- return Dom.CSharp.CSharpAmbience.Instance.Convert(entity as Dom.IMethod);
- if (entity is Dom.IProperty)
- return Dom.CSharp.CSharpAmbience.Instance.Convert(entity as Dom.IProperty);
- if (entity is Dom.IEvent)
- return Dom.CSharp.CSharpAmbience.Instance.Convert(entity as Dom.IEvent);
- if (entity is Dom.IField)
- return Dom.CSharp.CSharpAmbience.Instance.Convert(entity as Dom.IField);
- if (entity is Dom.IClass)
- return Dom.CSharp.CSharpAmbience.Instance.Convert(entity as Dom.IClass);
- // unknown entity:
- return entity.ToString();
- }
-
- int GetMemberImageIndex(Dom.IMember member)
- {
- // Missing: different icons for private/public member
- if (member is Dom.IMethod)
- return 1;
- if (member is Dom.IProperty)
- return 2;
- if (member is Dom.IField)
- return 3;
- if (member is Dom.IEvent)
- return 6;
- return 3;
- }
}
}
diff --git a/samples/CSharpCodeCompletion/MainForm.cs b/samples/CSharpCodeCompletion/MainForm.cs
index 7278c4f8b2..8d7605f47c 100644
--- a/samples/CSharpCodeCompletion/MainForm.cs
+++ b/samples/CSharpCodeCompletion/MainForm.cs
@@ -80,8 +80,9 @@ class MainClass
";
textEditorControl1.SetHighlighting("C#");
textEditorControl1.ShowEOLMarkers = false;
- CodeCompletionKeyHandler.Attach(this, textEditorControl1);
HostCallbackImplementation.Register(this);
+ CodeCompletionKeyHandler.Attach(this, textEditorControl1);
+ ToolTipProvider.Attach(this, textEditorControl1);
pcRegistry = new Dom.ProjectContentRegistry(); // Default .NET 2.0 registry
diff --git a/samples/CSharpCodeCompletion/ToolTipProvider.cs b/samples/CSharpCodeCompletion/ToolTipProvider.cs
new file mode 100644
index 0000000000..61fa8f004e
--- /dev/null
+++ b/samples/CSharpCodeCompletion/ToolTipProvider.cs
@@ -0,0 +1,146 @@
+// CSharp Editor Example with Code Completion
+// Copyright (c) 2007, Daniel Grunwald
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice, this list
+// of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// - Neither the name of the ICSharpCode team nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
+// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+using System;
+using System.Text;
+using ICSharpCode.SharpDevelop.Dom;
+using ICSharpCode.SharpDevelop.Dom.CSharp;
+using TextEditor = ICSharpCode.TextEditor;
+using NRefactoryResolver = ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver;
+
+namespace CSharpEditor
+{
+ sealed class ToolTipProvider
+ {
+ MainForm mainForm;
+ TextEditor.TextEditorControl editor;
+ CSharpExpressionFinder expressionFinder = new CSharpExpressionFinder(MainForm.DummyFileName);
+
+ private ToolTipProvider(MainForm mainForm, TextEditor.TextEditorControl editor)
+ {
+ this.mainForm = mainForm;
+ this.editor = editor;
+ }
+
+ public static void Attach(MainForm mainForm, TextEditor.TextEditorControl editor)
+ {
+ ToolTipProvider tp = new ToolTipProvider(mainForm, editor);
+ editor.ActiveTextAreaControl.TextArea.ToolTipRequest += tp.OnToolTipRequest;
+ }
+
+ void OnToolTipRequest(object sender, TextEditor.ToolTipRequestEventArgs e)
+ {
+ if (e.InDocument && !e.ToolTipShown) {
+ // SD2 requires subtracting 1 from the offset, this is fixed in the expression
+ // finder in SD3.
+ ExpressionResult expression = expressionFinder.FindFullExpression(
+ editor.Text,
+ editor.Document.PositionToOffset(e.LogicalPosition) - 1);
+
+ TextEditor.TextArea textArea = editor.ActiveTextAreaControl.TextArea;
+ NRefactoryResolver resolver = new NRefactoryResolver(mainForm.myProjectContent, mainForm.myProjectContent.Language);
+ ResolveResult rr = resolver.Resolve(expression,
+ textArea.Caret.Line,
+ textArea.Caret.Column,
+ MainForm.DummyFileName,
+ textArea.MotherTextEditorControl.Text);
+ string toolTipText = GetText(rr);
+ if (toolTipText != null) {
+ e.ShowToolTip(toolTipText);
+ }
+ }
+ }
+
+ static string GetText(ResolveResult result)
+ {
+ if (result == null) {
+ return null;
+ }
+ if (result is MixedResolveResult)
+ return GetText(((MixedResolveResult)result).PrimaryResult);
+ IAmbience ambience = new CSharpAmbience();
+ ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowAccessibility;
+ if (result is MemberResolveResult) {
+ return GetMemberText(ambience, ((MemberResolveResult)result).ResolvedMember);
+ } else if (result is LocalResolveResult) {
+ LocalResolveResult rr = (LocalResolveResult)result;
+ ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedNames
+ | ConversionFlags.ShowReturnType
+ | ConversionFlags.QualifiedNamesOnlyForReturnTypes;
+ StringBuilder b = new StringBuilder();
+ if (rr.IsParameter)
+ b.Append("parameter ");
+ else
+ b.Append("local variable ");
+ b.Append(ambience.Convert(rr.Field));
+ return b.ToString();
+ } else if (result is NamespaceResolveResult) {
+ return "namespace " + ((NamespaceResolveResult)result).Name;
+ } else if (result is TypeResolveResult) {
+ IClass c = ((TypeResolveResult)result).ResolvedClass;
+ if (c != null)
+ return GetMemberText(ambience, c);
+ else
+ return ambience.Convert(result.ResolvedType);
+ } else if (result is MethodResolveResult) {
+ MethodResolveResult mrr = result as MethodResolveResult;
+ IMethod m = mrr.GetMethodIfSingleOverload();
+ if (m != null)
+ return GetMemberText(ambience, m);
+ else
+ return "Overload of " + ambience.Convert(mrr.ContainingType) + "." + mrr.Name;
+ } else {
+ return null;
+ }
+ }
+
+ static string GetMemberText(IAmbience ambience, IDecoration member)
+ {
+ StringBuilder text = new StringBuilder();
+ if (member is IField) {
+ text.Append(ambience.Convert(member as IField));
+ } else if (member is IProperty) {
+ text.Append(ambience.Convert(member as IProperty));
+ } else if (member is IEvent) {
+ text.Append(ambience.Convert(member as IEvent));
+ } else if (member is IMethod) {
+ text.Append(ambience.Convert(member as IMethod));
+ } else if (member is IClass) {
+ text.Append(ambience.Convert(member as IClass));
+ } else {
+ text.Append("unknown member ");
+ text.Append(member.ToString());
+ }
+ string documentation = member.Documentation;
+ if (documentation != null && documentation.Length > 0) {
+ text.Append('\n');
+ text.Append(CodeCompletionData.XmlDocumentationToText(documentation));
+ }
+ return text.ToString();
+ }
+ }
+}