Browse Source

Removed CreateEventHandler from RefactoringProvider

added insertion of new event handlers
existing event handlers with matching signature are included in code completion

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3952 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
422a3263f7
  1. 26
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs
  2. 21
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj
  3. 208
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  4. 70
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs
  5. 55
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs
  6. 18
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs
  7. 11
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/RefactoringProvider.cs

26
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.XamlBinding @@ -28,7 +28,7 @@ namespace ICSharpCode.XamlBinding
XmlReader reader = XmlTextReader.Create(new StringReader(text));
int startTags = 0;
try {
while (reader.Read()) {
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.Element:
startTags++;
@ -47,5 +47,29 @@ namespace ICSharpCode.XamlBinding @@ -47,5 +47,29 @@ namespace ICSharpCode.XamlBinding
return false;
}
public static string GetNameAttributeValue(string text, int offset)
{
int index = XmlParser.GetActiveElementStartIndex(text, offset);
if (index == -1)
return null;
index = text.IndexOf(' ', index);
text = text.Substring(index);
int endIndex = text.IndexOfAny(new char[] { '<', '>' });
text = text.Substring(0, endIndex).Trim(' ', '\t', '\n', '\r');
string[] attributes = text.Split(new string[] {"=\"", "\""}, StringSplitOptions.None);
for (int i = 0; i < attributes.Length; i += 2) {
if (i + 1 < attributes.Length) {
if (attributes[i].Trim(' ', '\t', '\n', '\r').ToLowerInvariant() == "name")
return attributes[i + 1];
} else
break;
}
return null;
}
}
}

21
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlBinding.csproj

@ -36,6 +36,12 @@ @@ -36,6 +36,12 @@
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@ -43,6 +49,9 @@ @@ -43,6 +49,9 @@
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="XamlBinding.addin">
@ -56,6 +65,7 @@ @@ -56,6 +65,7 @@
<Compile Include="XamlClassReturnType.cs" />
<Compile Include="XamlCodeCompletionBinding.cs" />
<Compile Include="XamlCompilationUnit.cs" />
<Compile Include="XamlCompletionItem.cs" />
<Compile Include="XamlCompletionItemList.cs" />
<Compile Include="XamlExpressionContext.cs" />
<Compile Include="XamlExpressionFinder.cs" />
@ -95,4 +105,15 @@ @@ -95,4 +105,15 @@
<!--<Target Name="AfterBuild">
<Copy SourceFiles="@(CopyFile)" DestinationFolder="$(OutputPath)" />
</Target>-->
<ItemGroup>
<ProjectReference Include="..\..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\DisplayBindings\AvalonEdit.AddIn\AvalonEdit.AddIn.csproj">
<Project>{0162E499-42D0-409B-AA25-EED21F75336B}</Project>
<Name>AvalonEdit.AddIn</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
</Project>

208
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs

@ -38,13 +38,14 @@ namespace ICSharpCode.XamlBinding @@ -38,13 +38,14 @@ namespace ICSharpCode.XamlBinding
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{
XamlResolver resolver = new XamlResolver();
XmlElementPath path;
int offset;
switch (ch) {
case '<':
int prevLTCharPos = GetPreviousLTCharPos(editor.Document.Text, editor.Caret.Offset) + 1;
XmlElementPath elPath = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, prevLTCharPos);
if (elPath != null && elPath.Elements.Count > 0) {
ICompletionItemList list = CreateListForContext(editor, XamlContext.AtTag, elPath, null);
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, prevLTCharPos);
if (path != null && path.Elements.Count > 0) {
ICompletionItemList list = CreateListForContext(editor, XamlContext.AtTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
@ -60,7 +61,7 @@ namespace ICSharpCode.XamlBinding @@ -60,7 +61,7 @@ namespace ICSharpCode.XamlBinding
}
if (c != '/') {
string document = editor.Document.Text.Insert(offset, ">");
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(document, offset);
path = XmlParser.GetActiveElementStartPathAtIndex(document, offset);
if (path != null && path.Elements.Count > 0) {
QualifiedName last = path.Elements[path.Elements.Count - 1];
@ -74,12 +75,37 @@ namespace ICSharpCode.XamlBinding @@ -74,12 +75,37 @@ namespace ICSharpCode.XamlBinding
}
}
break;
case '"':
offset = editor.Caret.Offset;
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, offset);
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
editor.Document.Insert(offset, "\"");
editor.Caret.Offset = offset;
}
break;
case '{': // starting point for Markup Extension Completion
offset = editor.Caret.Offset;
if (offset > 0) {
int searchOffset = offset - 1;
char c = editor.Document.GetCharAt(searchOffset);
while (char.IsWhiteSpace(c)) {
searchOffset--;
c = editor.Document.GetCharAt(searchOffset);
}
if (XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && c == '"') {
editor.Document.Insert(offset, "}");
editor.Caret.Offset = offset;
}
}
break;
case ' ':
XmlElementPath ePath = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (ePath != null && ePath.Elements.Count > 0) {
ICompletionItemList list = CreateListForContext(editor, XamlContext.InTag, ePath, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, editor.Caret.Offset);
if (path != null && path.Elements.Count > 0) {
if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) {
ICompletionItemList list = CreateListForContext(editor, XamlContext.InTag, path, null);
editor.ShowCompletionWindow(list);
return CodeCompletionKeyPressResult.Completed;
}
}
break;
default:
@ -88,7 +114,7 @@ namespace ICSharpCode.XamlBinding @@ -88,7 +114,7 @@ namespace ICSharpCode.XamlBinding
if (offset > 0) {
char c = editor.Document.GetCharAt(offset - 1);
if (c == ' ' || c == '\t') {
XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, offset);
path = XmlParser.GetActiveElementStartPathAtIndex(editor.Document.Text, offset);
if (path != null && path.Elements.Count > 0) {
ICompletionItemList list = CreateListForContext(editor, XamlContext.InTag, path, null);
editor.ShowCompletionWindow(list);
@ -133,22 +159,27 @@ namespace ICSharpCode.XamlBinding @@ -133,22 +159,27 @@ namespace ICSharpCode.XamlBinding
switch (context) {
case XamlContext.AtTag:
list.Items.AddRange(standardItems);
list.Items.AddRange(CtrlSpaceForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column));
break;
case XamlContext.InTag:
list.Items.AddRange(CtrlSpaceForAttributeName(info, editor.Document.Text, new XamlExpressionContext(path, null, false)));
list.Items.AddRange(CreateListForAttributeName(info, editor.Document.Text, new XamlExpressionContext(path, null, false)));
break;
case XamlContext.InAttributeValue:
if (entity is IProperty) {
IProperty prop = entity as IProperty;
IClass c = prop.ReturnType.GetUnderlyingClass();
if (c.ClassType == ClassType.Enum) {
foreach (IField f in c.Fields) {
list.Items.Add(new XamlCompletionItem(f));
}
IReturnType type = prop.ReturnType;
if (type != null) {
TypeCompletion(type.GetUnderlyingClass(), list);
}
} else if (entity is IEvent) {
IEvent e = entity as IEvent;
IMethod invoker = GetInvokeMethod(e.ReturnType);
if (invoker == null)
break;
var item = path.Elements[path.Elements.Count - 1];
string name = Utils.GetNameAttributeValue(editor.Document.Text, editor.Caret.Offset);
list.Items.Add(new NewEventCompletionItem(e, (string.IsNullOrEmpty(name)) ? item.Name : name));
AddMatchingEventHandlers(editor, invoker, list.Items);
}
break;
}
@ -157,6 +188,80 @@ namespace ICSharpCode.XamlBinding @@ -157,6 +188,80 @@ namespace ICSharpCode.XamlBinding
return list;
}
static void AddMatchingEventHandlers(ITextEditor editor, IMethod delegateInvoker, List<ICompletionItem> list)
{
ParseInformation p = ParserService.GetParseInformation(editor.FileName);
var unit = p.MostRecentCompilationUnit;
var loc = editor.Document.OffsetToPosition(editor.Caret.Offset);
IClass c = unit.GetInnermostClass(loc.Line, loc.Column);
CompoundClass compound = c.GetCompoundClass() as CompoundClass;
if (compound != null) {
foreach (IClass part in compound.Parts) {
foreach (IMethod m in part.Methods) {
if (m.Parameters.Count != delegateInvoker.Parameters.Count)
continue;
if ((m.ReturnType != null && delegateInvoker.ReturnType != null) && m.ReturnType.DotNetName != delegateInvoker.ReturnType.DotNetName)
continue;
bool equal = true;
for (int i = 0; i < m.Parameters.Count; i++) {
equal &= CompareParameter(m.Parameters[i], delegateInvoker.Parameters[i]);
if (!equal)
break;
}
if (equal) {
list.Add(new XamlCompletionItem(m));
}
}
}
}
}
static bool CompareParameter(IParameter p1, IParameter p2)
{
bool result = p1.ReturnType.DotNetName == p2.ReturnType.DotNetName;
result &= (p1.IsOut == p2.IsOut);
result &= (p1.IsParams == p2.IsParams);
result &= (p1.IsRef == p2.IsRef);
return result;
}
static IMethod GetInvokeMethod(IReturnType type)
{
if (type == null)
return null;
foreach (IMethod method in type.GetMethods()) {
if (method.Name == "Invoke")
return method;
}
return null;
}
static bool TypeCompletion(IClass type, XamlCompletionItemList list)
{
switch (type.ClassType) {
case ClassType.Enum:
foreach (IField f in type.Fields) {
list.Items.Add(new XamlCompletionItem(f));
}
return true;
case ClassType.Struct:
if (type.FullyQualifiedName == "System.Boolean") {
list.Items.Add(new DefaultCompletionItem("True"));
list.Items.Add(new DefaultCompletionItem("False"));
return true;
}
break;
}
return false;
}
public bool CtrlSpace(ICSharpCode.SharpDevelop.ITextEditor editor)
{
@ -164,27 +269,8 @@ namespace ICSharpCode.XamlBinding @@ -164,27 +269,8 @@ namespace ICSharpCode.XamlBinding
// provider.ShowCompletion(editor);
return true;
}
// public ArrayList CtrlSpace(int caretLineNumber, int caretColumn, ParseInformation parseInfo, string fileContent, ExpressionContext expressionContext)
// {
// var callingClass = parseInfo.BestCompilationUnit.GetInnermostClass(caretLineNumber, caretColumn);
// var context = expressionContext as XamlExpressionContext;
// if (context == null) {
// return null;
// }
//
// if (context.AttributeName == null) {
// return CtrlSpaceForElement(fileContent);
// }
// else if (context.InAttributeValue) {
// return CtrlSpaceForAttributeValue(parseInfo, fileContent, context);
// }
// else {
// return CtrlSpaceForAttributeName(parseInfo, fileContent, context);
// }
// }
//
static List<ICompletionItem> CtrlSpaceForAttributeName(ParseInformation parseInfo, string fileContent, XamlExpressionContext context)
static List<ICompletionItem> CreateListForAttributeName(ParseInformation parseInfo, string fileContent, XamlExpressionContext context)
{
if (context.ElementPath.Elements.Count == 0)
return null;
@ -208,28 +294,7 @@ namespace ICSharpCode.XamlBinding @@ -208,28 +294,7 @@ namespace ICSharpCode.XamlBinding
}
return list;
}
//
// ArrayList CtrlSpaceForAttributeValue(ParseInformation parseInfo, string fileContent, XamlExpressionContext context)
// {
// ArrayList attributes = CtrlSpaceForAttributeName(parseInfo, fileContent, context);
// if (attributes != null) {
// foreach (IProperty p in attributes.OfType<IProperty>()) {
// if (p.Name == context.AttributeName && p.ReturnType != null) {
// IClass c = p.ReturnType.GetUnderlyingClass();
// if (c != null && c.ClassType == ClassType.Enum) {
// return EnumCompletion(c);
// }
// }
// }
// }
// return null;
// }
//
// ArrayList EnumCompletion(IClass enumClass)
// {
// }
//
static bool IsReaderAtTarget(XmlTextReader r, int caretLine, int caretColumn)
{
if (r.LineNumber > caretLine)
@ -240,7 +305,7 @@ namespace ICSharpCode.XamlBinding @@ -240,7 +305,7 @@ namespace ICSharpCode.XamlBinding
return false;
}
static List<ICompletionItem> CtrlSpaceForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
static List<ICompletionItem> CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn)
{
using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) {
try {
@ -283,25 +348,4 @@ namespace ICSharpCode.XamlBinding @@ -283,25 +348,4 @@ namespace ICSharpCode.XamlBinding
}
}
}
class XamlCompletionItem : DefaultCompletionItem
{
IEntity entity;
public IEntity Entity {
get { return entity; }
}
public XamlCompletionItem(IEntity entity, string prefix)
: base(prefix + ":" + entity.Name)
{
this.entity = entity;
}
public XamlCompletionItem(IEntity entity)
: base(entity.Name)
{
this.entity = entity;
}
}
}

70
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItem.cs

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision: 3731 $</version>
// </file>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.XmlEditor;
namespace ICSharpCode.XamlBinding
{
class XamlCompletionItem : DefaultCompletionItem
{
IEntity entity;
public IEntity Entity {
get { return entity; }
}
public XamlCompletionItem(IEntity entity, string prefix)
: base(prefix + ":" + entity.Name)
{
this.entity = entity;
}
public XamlCompletionItem(IEntity entity)
: base(entity.Name)
{
this.entity = entity;
}
}
class NewEventCompletionItem : DefaultCompletionItem
{
IEvent eventType;
public IEvent EventType {
get { return eventType; }
}
string targetName;
public string TargetName {
get { return targetName; }
}
public string HandlerName { get; set; }
public NewEventCompletionItem(IEvent eventType, string targetName)
: base("<new event handler>") // TODO : replace by resource string
{
this.eventType = eventType;
this.targetName = targetName;
}
public override void Complete(CompletionContext context)
{
context.Editor.Document.Replace(context.StartOffset, context.Length, this.HandlerName);
}
}
}

55
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs

@ -5,15 +5,17 @@ @@ -5,15 +5,17 @@
// <version>$Revision: 3731 $</version>
// </file>
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.AvalonEdit.AddIn;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.TextEditor.Gui.CompletionWindow;
@ -57,35 +59,62 @@ namespace ICSharpCode.XamlBinding @@ -57,35 +59,62 @@ namespace ICSharpCode.XamlBinding
}
}
} else {
if (item is DefaultCompletionItem) {
if (item.Text == "<new event handler>") { // TODO : replace with translation string
}
if (item is NewEventCompletionItem) {
NewEventCompletionItem eventItem = item as NewEventCompletionItem;
CreateEventHandlerCode(context, eventItem);
}
}
base.Complete(context, item);
}
string CreateEventHandlerCode(CompletionContext context, out IMember lastMember)
void CreateEventHandlerCode(CompletionContext context, NewEventCompletionItem completionItem)
{
ParseInformation p = ParserService.GetParseInformation(context.Editor.FileName);
var unit = p.MostRecentCompilationUnit;
var loc = context.Editor.Document.OffsetToPosition(context.StartOffset);
IClass c = unit.GetInnermostClass(loc.Line, loc.Column);
IMethod initializeComponent = c.Methods[0];
CompoundClass compound = c.GetCompoundClass() as CompoundClass;
if (compound != null) {
foreach (IClass part in compound.Parts) {
RefactoringProvider provider = part.ProjectContent.Language.RefactoringProvider;
if (provider.SupportsCreateEventHandler) {
lastMember = part.Methods.Last();
//return provider.CreateEventHandler(;
IMember lastMember = part.Methods.LastOrDefault();
if (lastMember != null && lastMember.ToString() == initializeComponent.ToString())
continue;
if (completionItem.EventType.ReturnType == null)
return;
IMethod method = completionItem.EventType.ReturnType.GetMethods().FirstOrDefault(m => m.Name == "Invoke");
if (method == null)
throw new ArgumentException("delegateType is not a valid delegate!");
ParametrizedNode node = CodeGenerator.ConvertMember(method, new ClassFinder(part, context.Editor.Caret.Line, context.Editor.Caret.Column));
// TODO : add formatting options ...
node.Name = completionItem.TargetName + "_" + completionItem.EventType.Name;
completionItem.HandlerName = node.Name;
node.Modifier = Modifiers.None;
AvalonEditViewContent viewContent = FileService.OpenFile(part.CompilationUnit.FileName) as AvalonEditViewContent;
// TODO : shouldn't we be able to use viewContent.CodeEditor.textEditorAdapter here? (Property missing?)
ITextEditor wrapper = new CodeEditorAdapter(viewContent.CodeEditor);
if (viewContent != null) {
if (lastMember != null)
unit.ProjectContent.Language.CodeGenerator.InsertCodeAfter(lastMember, wrapper.Document, node);
else
unit.ProjectContent.Language.CodeGenerator.InsertCodeAtEnd(part.Region, wrapper.Document, node);
return;
}
return;
}
}
lastMember = null;
return string.Empty;
}
}
}

18
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs

@ -618,23 +618,5 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -618,23 +618,5 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
|| trimLine.StartsWith("#if", StringComparison.Ordinal);
}
#endregion
#region CreateEventHandler
public override bool SupportsCreateEventHandler {
get { return true; }
}
public override string CreateEventHandler(string senderName, string eventName, IEvent e)
{
string text = "";
text += "void " + senderName + eventName + "(object sender, " + e.FullyQualifiedName + " e)\n" +
"{\n" +
"\tthrow new NotImplementedException();\n" +
"}\n";
return text;
}
#endregion
}
}

11
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/RefactoringProvider.cs

@ -93,17 +93,6 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -93,17 +93,6 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
throw new NotSupportedException();
}
#endregion
#region CreateEventHandler
public virtual bool SupportsCreateEventHandler {
get { return false; }
}
public virtual string CreateEventHandler(string senderName, string eventName, IEvent e)
{
throw new NotSupportedException();
}
#endregion
}
}

Loading…
Cancel
Save