From d595bff51e1694892623a134e0965583fc09df10 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 23 Apr 2006 12:10:31 +0000 Subject: [PATCH] Implemented code-completion for Boo's CallableTypeReference. Added Boo resolver unit tests. Added workaround for IME crash in WOW64 mode. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1339 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/AddIns/BackendBindings/Boo/BooBinding.sln | 10 +- .../Src/CodeCompletion/ConvertVisitor.cs | 21 ++- .../Src/CodeCompletion/InferredReturnType.cs | 3 +- .../Src/CodeCompletion/ResolveVisitor.cs | 23 ++- .../CodeCompletion/VariableLookupVisitor.cs | 34 ++++- .../BooBinding/Test/BooBinding.Tests.csproj | 74 +++++++++ .../Boo/BooBinding/Test/ResolverTests.cs | 142 ++++++++++++++++++ .../src/Service/Help2RegistryWalker.cs | 4 +- .../Project/Src/Gui/Ime.cs | 54 ++++--- .../AnonymousMethodReturnType.cs | 86 ++++++++++- .../NRefactoryASTConvertVisitor.cs | 44 +++--- .../Src/Dom/NRefactoryResolver/TypeVisitor.cs | 6 +- 12 files changed, 436 insertions(+), 65 deletions(-) create mode 100644 src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj create mode 100644 src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs diff --git a/src/AddIns/BackendBindings/Boo/BooBinding.sln b/src/AddIns/BackendBindings/Boo/BooBinding.sln index aafaa2a3d8..02bc32ff2a 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.0.0.1199 +# SharpDevelop 2.1.0.1333 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}" @@ -8,8 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneConverter", "Stan EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" EndProject -Project("{A33008B1-5DAC-44D5-9060-242E3B6E38F2}") = "Boo.InterpreterAddIn", "Boo.InterpreterAddIn\Project\Boo.InterpreterAddIn.booproj", "{928E34B2-5E46-4A4D-8E4D-2CA2CCDB905A}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "..\..\..\Libraries\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TextEditor", "..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" @@ -22,6 +20,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsUI", "..\..\..\Libr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "..\..\DisplayBindings\FormsDesigner\Project\FormsDesigner.csproj", "{7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding.Tests", "BooBinding\Test\BooBinding.Tests.csproj", "{6FA16499-896F-4C02-BB43-1AF5C6C7C713}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -80,5 +80,9 @@ Global {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Release|Any CPU.Build.0 = Release|Any CPU {83DD7E12-A705-4DBA-9D71-09C8973D9382}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FA16499-896F-4C02-BB43-1AF5C6C7C713}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FA16499-896F-4C02-BB43-1AF5C6C7C713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FA16499-896F-4C02-BB43-1AF5C6C7C713}.Release|Any CPU.Build.0 = Release|Any CPU + {6FA16499-896F-4C02-BB43-1AF5C6C7C713}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection EndGlobal 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 a81fdd665d..d38e632df6 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs @@ -177,7 +177,7 @@ namespace Grunwald.BooBinding.CodeCompletion if (parameters == null || parameters.Count == 0) { m.Parameters = DefaultParameter.EmptyParameterList; } else { - AddParameters(parameters, m.Parameters); + AddParameters(parameters, m.Parameters, m, m.DeclaringType); } } void ConvertParameters(AST.ParameterDeclarationCollection parameters, DefaultProperty p) @@ -185,14 +185,17 @@ namespace Grunwald.BooBinding.CodeCompletion if (parameters == null || parameters.Count == 0) { p.Parameters = DefaultParameter.EmptyParameterList; } else { - AddParameters(parameters, p.Parameters); + AddParameters(parameters, p.Parameters, p, p.DeclaringType); } } - void AddParameters(AST.ParameterDeclarationCollection parameters, IList output) + internal static void AddParameters(AST.ParameterDeclarationCollection parameters, IList output, IMethodOrProperty method, IClass c) { + if (c == null) throw new ArgumentNullException("c"); DefaultParameter p = null; foreach (AST.ParameterDeclaration par in parameters) { - p = new DefaultParameter(par.Name, CreateReturnType(par.Type), GetRegion(par)); + p = new DefaultParameter(par.Name, + CreateReturnType(par.Type, c, method as IMethod, c.Region.BeginLine + 1, 1, c.ProjectContent), + new DomRegion(par.LexicalInfo.Line, par.LexicalInfo.Column)); if (par.IsByRef) p.Modifiers |= ParameterModifiers.Ref; output.Add(p); } @@ -211,7 +214,7 @@ namespace Grunwald.BooBinding.CodeCompletion } } public static IReturnType CreateReturnType(AST.TypeReference reference, IClass callingClass, - IMember callingMember, int caretLine, int caretColumn, + IMethodOrProperty callingMember, int caretLine, int caretColumn, IProjectContent projectContent) { if (reference == null) { @@ -244,7 +247,13 @@ namespace Grunwald.BooBinding.CodeCompletion } return rt; } else if (reference is AST.CallableTypeReference) { - return new AnonymousMethodReturnType(); + AST.CallableTypeReference ctr = (AST.CallableTypeReference)reference; + AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(new DefaultCompilationUnit(projectContent)); + if (ctr.ReturnType != null) { + amrt.MethodReturnType = CreateReturnType(ctr.ReturnType, callingClass, callingMember, caretLine, caretColumn, projectContent); + } + AddParameters(ctr.Parameters, amrt.MethodParameters, callingMember, callingClass ?? new DefaultClass(new DefaultCompilationUnit(projectContent), "__Dummy")); + return amrt; } else { throw new NotSupportedException("unknown reference type: " + reference.ToString()); } diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs index b22907b257..108501b8b8 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs @@ -82,7 +82,8 @@ namespace Grunwald.BooBinding.CodeCompletion public override void OnYieldStatement(YieldStatement node) { noReturnStatement = false; - result = ReflectionReturnType.CreatePrimitive(typeof(System.Collections.IEnumerable)); + IClass enumerable = ProjectContentRegistry.Mscorlib.GetClass("System.Collections.Generic.IEnumerable", 1); + result = new ConstructedReturnType(enumerable.DefaultReturnType, new IReturnType[] { new InferredReturnType(node.Expression, context) }); } public override bool Visit(Node node) diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs index db124e05e3..10f2340b08 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs @@ -291,6 +291,17 @@ namespace Grunwald.BooBinding.CodeCompletion } } else { if (resolveResult != null) { + if (resolveResult is TypeResolveResult) { + IClass rClass = (resolveResult as TypeResolveResult).ResolvedClass; + if (rClass != null) { + foreach (IClass innerClass in rClass.InnerClasses) { + if (IsSameName(innerClass.Name, node.Name)) { + MakeTypeResult(innerClass); + return; + } + } + } + } ResolveMember(resolveResult.ResolvedType, node.Name); } } @@ -531,8 +542,6 @@ namespace Grunwald.BooBinding.CodeCompletion case BinaryOperatorType.Member: case BinaryOperatorType.NotMatch: case BinaryOperatorType.NotMember: - case BinaryOperatorType.Or: - case BinaryOperatorType.And: case BinaryOperatorType.ReferenceEquality: case BinaryOperatorType.ReferenceInequality: case BinaryOperatorType.TypeTest: @@ -566,7 +575,15 @@ namespace Grunwald.BooBinding.CodeCompletion public override void OnCallableBlockExpression(CallableBlockExpression node) { - MakeResult(new AnonymousMethodReturnType()); + AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(cu); + if (node.ReturnType != null) { + amrt.MethodReturnType = ConvertType(node.ReturnType); + } else { + + amrt.MethodReturnType = new InferredReturnType(node.Body, resolver.CallingClass); + } + ConvertVisitor.AddParameters(node.Parameters, amrt.MethodParameters, resolver.CallingMember, resolver.CallingClass ?? new DefaultClass(resolver.CompilationUnit, "__Dummy")); + MakeResult(amrt); } public override void OnCallableTypeReference(CallableTypeReference node) 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 a300b118d6..fe3d985e40 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/VariableLookupVisitor.cs @@ -26,9 +26,28 @@ namespace Grunwald.BooBinding.CodeCompletion DeclarationFound(node.Declaration.Name, node.Declaration.Type, node.Initializer, node.LexicalInfo); } - public override void OnParameterDeclaration(ParameterDeclaration node) + LexicalInfo GetEndSourceLocation(Node node) + { + if (node.LexicalInfo.IsValid) return node.LexicalInfo; + if (node is CallableBlockExpression) { + return GetEndSourceLocation((node as CallableBlockExpression).Body); + } else if (node is Block) { + StatementCollection st = (node as Block).Statements; + if (st.Count > 0) { + return GetEndSourceLocation(st[st.Count - 1]); + } + } + return node.LexicalInfo; + } + + public override void OnCallableBlockExpression(CallableBlockExpression node) { - DeclarationFound(node.Name, node.Type, null, node.LexicalInfo); + if (node.LexicalInfo.Line <= resolver.CaretLine && GetEndSourceLocation(node).Line >= resolver.CaretLine - 1) { + foreach (ParameterDeclaration param in node.Parameters) { + DeclarationFound(param.Name, param.Type, null, param.LexicalInfo); + } + base.OnCallableBlockExpression(node); + } } protected override void OnError(Node node, Exception error) @@ -51,7 +70,7 @@ namespace Grunwald.BooBinding.CodeCompletion public override void OnForStatement(ForStatement node) { - if (node.LexicalInfo.Line <= resolver.CaretLine && node.Block.EndSourceLocation.Line >= resolver.CaretLine - 1) { + if (node.LexicalInfo.Line <= resolver.CaretLine && GetEndSourceLocation(node).Line >= resolver.CaretLine - 1) { foreach (Declaration decl in node.Declarations) { IterationDeclarationFound(decl.Name, decl.Type, node.Iterator, node.LexicalInfo); } @@ -142,7 +161,14 @@ namespace Grunwald.BooBinding.CodeCompletion { if (expr == null) return; - IReturnType returnType = new InferredReturnType(expr, resolver.CallingClass); + // Prevent creating an infinite number of InferredReturnTypes in inferring cycles + IReturnType returnType; + if (expr.ContainsAnnotation("DomReturnType")) { + returnType = (IReturnType)expr["DomReturnType"]; + } else { + returnType = new InferredReturnType(expr, resolver.CallingClass); + expr.Annotate("DomReturnType", returnType); + } if (useElementType) returnType = new ElementReturnType(returnType); result = new DefaultField.LocalVariableField(returnType, name, diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj b/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj new file mode 100644 index 0000000000..c507a76e3f --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj @@ -0,0 +1,74 @@ + + + Library + Grunwald.BooBinding.Tests + BooBinding.Tests + Debug + AnyCPU + {6FA16499-896F-4C02-BB43-1AF5C6C7C713} + ..\..\..\..\..\..\bin\UnitTests\ + False + False + False + Auto + 4194304 + AnyCPU + 4096 + 4 + false + + + obj\ + obj\Debug\ + False + DEBUG;TRACE + true + Full + True + + + obj\ + obj\Release\ + True + TRACE + False + None + False + + + + + + + + + + + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + + + {4AC2D5F1-F671-480C-A075-6BF62B3721B2} + BooBinding + + + log4net.dll + Always + + + ICSharpCode.Core.dll + Always + + + ICSharpCode.SharpDevelop.dll + Always + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs new file mode 100644 index 0000000000..84a612f889 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Test/ResolverTests.cs @@ -0,0 +1,142 @@ +/* + * Created by SharpDevelop. + * User: Daniel Grunwald + * Date: 23.04.2006 + * Time: 11:33 + */ + +using System; +using NUnit.Framework; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using Grunwald.BooBinding.CodeCompletion; + +namespace Grunwald.BooBinding.Tests +{ + [TestFixture] + public class ResolverTests + { + T Resolve(string code) where T : ResolveResult + { + return Resolve(code, "/*1*/"); + } + + T Resolve(string code, string marker) where T : ResolveResult + { + ResolveResult rr = Resolve(prog, new ExpressionResult(code), marker); + Assert.IsNotNull(rr, "Resolve must not return null"); + Assert.IsInstanceOfType(typeof(T), rr, "Resolve must return instance of type " + typeof(T).Name); + return (T)rr; + } + + ResolveResult Resolve(string prog, ExpressionResult er, string marker) + { + const string fileName = "tempFile.boo"; + DefaultProjectContent pc = new DefaultProjectContent(); + ParserService.ForceProjectContent(pc); + pc.ReferencedContents.Add(ProjectContentRegistry.Mscorlib); + pc.ReferencedContents.Add(ProjectContentRegistry.WinForms); + ICompilationUnit cu = new BooParser().Parse(pc, fileName, prog); + ParserService.UpdateParseInformation(cu, fileName, false, false); + cu.Classes.ForEach(pc.AddClassToNamespaceList); + + int index = prog.IndexOf(marker); + int line = 1; + int column = 0; + for (int i = 0; i < index; i++) { + column++; + if (prog[i]=='\n') { + line++; + column = 0; + } + } + + BooResolver r = new BooResolver(); + return r.Resolve(er, line, column, fileName, prog); + } + + const string prog = + "import System\n" + + "def MyMethod(arg as string):\n" + + "\tlocalVar = arg\n" + + "\t/*1*/\n" + + "\tclosure = { e as string | arg.IndexOf(e) /*inClosure*/ }\n" + + "\tindex = closure('.')\n" + + "\t/*2*/\n" + + "\tclosure2 = def(e as DateTime):\n" + + "\t\treturn e.Year\n" + + "\trecursiveClosure = def():\n" + + "\t\treturn recursiveClosure()\n" + + "\t/*3*/\n"; + + [Test] + public void MethodParameter() + { + LocalResolveResult rr = Resolve("arg"); + Assert.IsTrue(rr.IsParameter); + Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); + } + + [Test] + public void LocalVariable() + { + LocalResolveResult rr = Resolve("localVar"); + Assert.IsFalse(rr.IsParameter); + Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); + } + + [Test] + public void NullCoalescing() + { + ResolveResult rr = Resolve("localVar or arg"); + Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); + } + + [Test] + public void InnerClassEnum() + { + TypeResolveResult trr = Resolve("Environment.SpecialFolder"); + Assert.AreEqual("System.Environment.SpecialFolder", trr.ResolvedClass.FullyQualifiedName); + + MemberResolveResult mrr = Resolve("Environment.SpecialFolder.Desktop"); + Assert.AreEqual("System.Environment.SpecialFolder.Desktop", mrr.ResolvedMember.FullyQualifiedName); + } + + [Test] + public void ClosureParameter() + { + LocalResolveResult rr = Resolve("e", "/*inClosure*/"); + Assert.AreEqual("System.String", rr.ResolvedType.FullyQualifiedName); + + Assert.IsNull(Resolve(prog, new ExpressionResult("e"), "/*1*/")); + } + + [Test] + public void ClosureCall() + { + LocalResolveResult rr = Resolve("closure('.')", "/*2*/"); + Assert.IsFalse(rr.IsParameter); + Assert.AreEqual("closure", rr.Field.Name); + Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName); + } + + [Test] + public void ClosureCall2() + { + LocalResolveResult rr = Resolve("closure2(DateTime.Now)", "/*3*/"); + Assert.IsFalse(rr.IsParameter); + Assert.AreEqual("closure2", rr.Field.Name); + Assert.AreEqual("System.Int32", rr.ResolvedType.FullyQualifiedName); + } + + [Test] + public void RecursiveClosure() + { + // Code-completion cannot work here, test if SharpDevelop is correctly + // preventing the StackOverflow. + LocalResolveResult rr = Resolve("recursiveClosure", "/*3*/"); + Assert.IsFalse(rr.IsParameter); + Assert.AreEqual("delegate():?", rr.ResolvedType.FullyQualifiedName); + } + } +} diff --git a/src/AddIns/Misc/HtmlHelp2/Project/src/Service/Help2RegistryWalker.cs b/src/AddIns/Misc/HtmlHelp2/Project/src/Service/Help2RegistryWalker.cs index 4ac8e42c21..ddfc832141 100644 --- a/src/AddIns/Misc/HtmlHelp2/Project/src/Service/Help2RegistryWalker.cs +++ b/src/AddIns/Misc/HtmlHelp2/Project/src/Service/Help2RegistryWalker.cs @@ -55,9 +55,9 @@ namespace HtmlHelp2.RegistryWalker else help2Collections.SelectedIndex = 0; } - catch + catch(Exception ex) { - LoggingService.Error("Help 2.0: cannot build namespaces list for Options dialog"); + LoggingService.Error("Help 2.0: cannot build namespaces list for Options dialog", ex); } help2Collections.EndUpdate(); diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Ime.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Ime.cs index 8334f73a76..bf5b3012ca 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Ime.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Ime.cs @@ -8,6 +8,7 @@ using System; using System.Runtime.InteropServices; using System.Drawing; +using System.Windows.Forms; namespace ICSharpCode.TextEditor { @@ -31,15 +32,11 @@ namespace ICSharpCode.TextEditor return font; } set { - if (font == null) { + if (!value.Equals(font)) { font = value; lf = null; + SetIMEWindowFont(value); } - else if (font.Equals(value) == false) { - font = value; - lf = null; - } - SetIMEWindowFont(value); } } @@ -113,25 +110,33 @@ namespace ICSharpCode.TextEditor } private const int IMC_SETCOMPOSITIONFONT = 0x000a; LOGFONT lf = null; + static bool disableIME; private void SetIMEWindowFont(Font f) { + if (disableIME || hIMEWnd == IntPtr.Zero) return; + if (lf == null) { lf = new LOGFONT(); f.ToLogFont(lf); lf.lfFaceName = f.Name; // This is very important! "Font.ToLogFont" Method sets invalid value to LOGFONT.lfFaceName } - SendMessage( - hIMEWnd, - WM_IME_CONTROL, - new IntPtr(IMC_SETCOMPOSITIONFONT), - lf - ); + try { + SendMessage( + hIMEWnd, + WM_IME_CONTROL, + new IntPtr(IMC_SETCOMPOSITIONFONT), + lf + ); + } catch (AccessViolationException ex) { + Handle(ex); + } } public void SetIMEWindowLocation(int x, int y) { + if (disableIME || hIMEWnd == IntPtr.Zero) return; POINT p = new POINT(); p.x = x; @@ -142,12 +147,25 @@ namespace ICSharpCode.TextEditor lParam.ptCurrentPos = p; lParam.rcArea = new RECT(); - SendMessage( - hIMEWnd, - WM_IME_CONTROL, - new IntPtr(IMC_SETCOMPOSITIONWINDOW), - lParam - ); + try { + SendMessage( + hIMEWnd, + WM_IME_CONTROL, + new IntPtr(IMC_SETCOMPOSITIONWINDOW), + lParam + ); + } catch (AccessViolationException ex) { + Handle(ex); + } + } + + void Handle(Exception ex) + { + Console.WriteLine(ex); + if (!disableIME) { + disableIME = true; + MessageBox.Show("Error calling IME: " + ex.Message + "\nIME is disabled.", "IME error"); + } } } } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/AnonymousMethodReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/AnonymousMethodReturnType.cs index 4a4b369e62..7e33697378 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/AnonymousMethodReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/AnonymousMethodReturnType.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.Text; using ICSharpCode.Core; namespace ICSharpCode.SharpDevelop.Dom @@ -16,15 +17,81 @@ namespace ICSharpCode.SharpDevelop.Dom /// public sealed class AnonymousMethodReturnType : ProxyReturnType { + IReturnType returnType; + List parameters = new List(); + ICompilationUnit cu; + + public AnonymousMethodReturnType(ICompilationUnit cu) + { + this.cu = cu; + } + + /// + /// Return type of the anonymous method. Can be null if inferred from context. + /// + public IReturnType MethodReturnType { + get { + return returnType; + } + set { + returnType = value; + } + } + + /// + /// Gets the list of method parameters. + /// + public IList MethodParameters { + get { + return parameters; + } + } + public override bool IsDefaultReturnType { get { return false; } } + volatile DefaultClass cachedClass; + + public override IClass GetUnderlyingClass() + { + if (cachedClass != null) return cachedClass; + DefaultClass c = new DefaultClass(cu, ClassType.Delegate, ModifierEnum.None, DomRegion.Empty, null); + c.BaseTypes.Add(ReflectionReturnType.CreatePrimitive(typeof(Delegate))); + AddDefaultDelegateMethod(c, returnType ?? ReflectionReturnType.Object, parameters); + cachedClass = c; + return c; + } + + internal static void AddDefaultDelegateMethod(DefaultClass c, IReturnType returnType, IList parameters) + { + DefaultMethod invokeMethod = new DefaultMethod("Invoke", returnType, ModifierEnum.Public, c.Region, DomRegion.Empty, c); + foreach (IParameter par in parameters) { + invokeMethod.Parameters.Add(par); + } + c.Methods.Add(invokeMethod); + invokeMethod = new DefaultMethod("BeginInvoke", CreateReturnType(typeof(IAsyncResult)), ModifierEnum.Public, c.Region, DomRegion.Empty, c); + foreach (IParameter par in parameters) { + invokeMethod.Parameters.Add(par); + } + invokeMethod.Parameters.Add(new DefaultParameter("callback", CreateReturnType(typeof(AsyncCallback)), DomRegion.Empty)); + invokeMethod.Parameters.Add(new DefaultParameter("object", ReflectionReturnType.Object, DomRegion.Empty)); + c.Methods.Add(invokeMethod); + invokeMethod = new DefaultMethod("EndInvoke", returnType, ModifierEnum.Public, c.Region, DomRegion.Empty, c); + invokeMethod.Parameters.Add(new DefaultParameter("result", CreateReturnType(typeof(IAsyncResult)), DomRegion.Empty)); + c.Methods.Add(invokeMethod); + } + + static IReturnType CreateReturnType(Type type) + { + return ReflectionReturnType.Create(ProjectContentRegistry.Mscorlib, null, type, false); + } + public override IReturnType BaseType { get { - return ReflectionReturnType.Delegate; + return GetUnderlyingClass().DefaultReturnType; } } @@ -36,7 +103,22 @@ namespace ICSharpCode.SharpDevelop.Dom public override string FullyQualifiedName { get { - return Name; + StringBuilder b = new StringBuilder("delegate("); + bool first = true; + foreach (IParameter p in parameters) { + if (first) first = false; else b.Append(", "); + b.Append(p.Name); + if (p.ReturnType != null) { + b.Append(":"); + b.Append(p.ReturnType.Name); + } + } + b.Append(")"); + if (returnType != null) { + b.Append(":"); + b.Append(returnType.Name); + } + return b.ToString(); } } diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs index c77b38a92d..2a8647ec8d 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs @@ -389,25 +389,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } currentClass.Push(c); // necessary for CreateReturnType ConvertTemplates(templates, c); - DefaultMethod invokeMethod = new DefaultMethod("Invoke", CreateReturnType(returnType), ModifierEnum.Public, c.Region, DomRegion.Empty, c); - if (parameters != null) { - foreach (AST.ParameterDeclarationExpression par in parameters) { - invokeMethod.Parameters.Add(CreateParameter(par)); - } - } - c.Methods.Add(invokeMethod); - invokeMethod = new DefaultMethod("BeginInvoke", CreateReturnType(typeof(IAsyncResult)), ModifierEnum.Public, c.Region, DomRegion.Empty, c); + + List p = new List(); if (parameters != null) { - foreach (AST.ParameterDeclarationExpression par in parameters) { - invokeMethod.Parameters.Add(CreateParameter(par)); + foreach (AST.ParameterDeclarationExpression param in parameters) { + p.Add(CreateParameter(param)); } } - invokeMethod.Parameters.Add(new DefaultParameter("callback", CreateReturnType(typeof(AsyncCallback)), DomRegion.Empty)); - invokeMethod.Parameters.Add(new DefaultParameter("object", ReflectionReturnType.Object, DomRegion.Empty)); - c.Methods.Add(invokeMethod); - invokeMethod = new DefaultMethod("EndInvoke", CreateReturnType(returnType), ModifierEnum.Public, c.Region, DomRegion.Empty, c); - invokeMethod.Parameters.Add(new DefaultParameter("result", CreateReturnType(typeof(IAsyncResult)), DomRegion.Empty)); - c.Methods.Add(invokeMethod); + AnonymousMethodReturnType.AddDefaultDelegateMethod(c, CreateReturnType(returnType), p); + currentClass.Pop(); } @@ -418,7 +408,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver IParameter CreateParameter(AST.ParameterDeclarationExpression par, IMethod method) { - IReturnType parType = CreateReturnType(par.TypeReference, method); + return CreateParameter(par, method, GetCurrentClass(), cu); + } + + internal static IParameter CreateParameter(AST.ParameterDeclarationExpression par, IMethod method, IClass currentClass, ICompilationUnit cu) + { + IReturnType parType = CreateReturnType(par.TypeReference, method, currentClass, cu); DefaultParameter p = new DefaultParameter(par.ParameterName, parType, new DomRegion(par.StartLocation, par.EndLocation)); p.Modifiers = (ParameterModifiers)par.ParamModifier; return p; @@ -597,11 +592,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver IReturnType CreateReturnType(AST.TypeReference reference, IMethod method) { - IClass c = GetCurrentClass(); - if (c == null) { + return CreateReturnType(reference, method, GetCurrentClass(), cu); + } + + static IReturnType CreateReturnType(AST.TypeReference reference, IMethod method, IClass currentClass, ICompilationUnit cu) + { + if (currentClass == null) { return TypeVisitor.CreateReturnType(reference, new DefaultClass(cu, "___DummyClass"), method, 1, 1, cu.ProjectContent, true); } else { - return TypeVisitor.CreateReturnType(reference, c, method, c.Region.BeginLine + 1, 1, cu.ProjectContent, true); + return TypeVisitor.CreateReturnType(reference, currentClass, method, currentClass.Region.BeginLine + 1, 1, cu.ProjectContent, true); } } @@ -609,10 +608,5 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver { return CreateReturnType(reference, null); } - - IReturnType CreateReturnType(Type type) - { - return ReflectionReturnType.Create(ProjectContentRegistry.Mscorlib, null, type, false); - } } } diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs index 0e536b8e98..0e05c3e2e8 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs @@ -428,7 +428,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public override object Visit(AnonymousMethodExpression anonymousMethodExpression, object data) { - return new AnonymousMethodReturnType(); + AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(resolver.CompilationUnit); + foreach (ParameterDeclarationExpression param in anonymousMethodExpression.Parameters) { + amrt.MethodParameters.Add(NRefactoryASTConvertVisitor.CreateParameter(param, resolver.CallingMember as IMethod, resolver.CallingClass, resolver.CompilationUnit)); + } + return amrt; } public override object Visit(ArrayInitializerExpression arrayInitializerExpression, object data)