diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index aeee45d439..464c2e4e10 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -272,10 +272,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion // case 1) // check if the object is a list, if not only provide object initalizers - var list = typeof (System.Collections.IList).ToTypeReference ().Resolve (Compilation); + var list = typeof(System.Collections.IList).ToTypeReference().Resolve(Compilation); if (initializerResult.Item1.Type.Kind != TypeKind.Array && list != null) { - var def = initializerResult.Item1.Type.GetDefinition (); - if (def != null && !def.IsDerivedFrom (list.GetDefinition ())) + var def = initializerResult.Item1.Type.GetDefinition(); + if (def != null && !def.IsDerivedFrom(list.GetDefinition())) return contextList.Result; } @@ -548,7 +548,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } } if (token == "+=") { - string parameterDefinition = AddDelegateHandlers(wrapper, delegateType); + string parameterDefinition = AddDelegateHandlers( + wrapper, + delegateType + ); string varName = GetPreviousMemberReferenceExpression(tokenIndex); wrapper.Result.Add( factory.CreateEventCreationCompletionData( @@ -640,7 +643,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion // May happen in variable names return controlSpace ? DefaultControlSpaceItems(identifierStart) : null; } - if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) { return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null; } @@ -716,19 +718,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return null; } - var astResolver = new CSharpAstResolver( - GetState(), - identifierStart.Unit, - CSharpParsedFile - ); - - foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)n)) { - if (type.Kind == TypeKind.Delegate) { - AddDelegateHandlers(contextList, type, false, false); - AutoSelect = false; - AutoCompleteEmptyMatch = false; - } - } +// var astResolver = new CSharpAstResolver( +// GetState(), +// identifierStart.Unit, +// CSharpParsedFile +// ); +// +// foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)n)) { +// if (type.Kind == TypeKind.Delegate) { +// AddDelegateHandlers(contextList, type, false, false); +// AutoSelect = false; +// AutoCompleteEmptyMatch = false; +// } +// } } // Handle object/enumerable initialzer expressions: "new O () { P$" @@ -1000,7 +1002,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var wrapper = new CompletionDataWrapper(this); AddTypesAndNamespaces( wrapper, - GetState (), + GetState(), identifierStart.Node, typePred, m => false @@ -1060,7 +1062,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion while (null != (token = GetPreviousToken (ref offset, true)) && !IsInsideCommentStringOrDirective ()) { if (token == "from") { - return !IsInsideCommentStringOrDirective (offset); + return !IsInsideCommentStringOrDirective(offset); } if (token == ";" || token == "{") { return false; @@ -1113,11 +1115,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion rr = ResolveExpression(node, xp.Unit); unit = xp.Unit; } else { - unit = ParseStub("a", false); - node = unit.GetNodeAt(location); + unit = ParseStub("foo", false); + node = unit.GetNodeAt( + location.Line, + location.Column + 2, + n => n is Expression || n is AstType + ); rr = ResolveExpression(node, unit); } - if (node is Identifier && node.Parent is ForeachStatement) { var foreachStmt = (ForeachStatement)node.Parent; foreach (var possibleName in GenerateNameProposals (foreachStmt.VariableType)) { @@ -1186,7 +1191,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion csResolver = GetState(); } } - AddContextCompletion(wrapper, csResolver, node, unit); return wrapper.Result; @@ -1224,7 +1228,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null; }; } - AddTypesAndNamespaces(wrapper, state, node, typePred); wrapper.Result.Add(factory.CreateLiteralCompletionData("global")); @@ -1281,6 +1284,24 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } } + if (node is Expression) { + var astResolver = new CSharpAstResolver(state, unit, CSharpParsedFile); + foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)node)) { + if (type.Kind == TypeKind.Enum) { + AddEnumMembers(wrapper, type, state); + } else if (type.Kind == TypeKind.Delegate) { + AddDelegateHandlers(wrapper, type, true, true); + AutoSelect = false; + AutoCompleteEmptyMatch = false; + } + } + } + + // Add 'this' keyword for first parameter (extension method case) + if (node != null && node.Parent is ParameterDeclaration && + node.Parent.PrevSibling != null && node.Parent.PrevSibling.Role == Roles.LPar) { + wrapper.AddCustom("this"); + } } static bool IsInSwitchContext(AstNode node) @@ -1300,6 +1321,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func typePred = null, Predicate memberPred = null, Action callback = null) { + var lookup = new MemberLookup( + ctx.CurrentTypeDefinition, + Compilation.MainAssembly + ); if (currentType != null) { for (var ct = currentType; ct != null; ct = ct.DeclaringTypeDefinition) { foreach (var nestedType in ct.NestedTypes) { @@ -1326,10 +1351,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (this.currentMember != null && !(node is AstType)) { var def = ctx.CurrentTypeDefinition ?? Compilation.MainAssembly.GetTypeDefinition(currentType); if (def != null) { - var lookup = new MemberLookup( - ctx.CurrentTypeDefinition, - Compilation.MainAssembly - ); bool isProtectedAllowed = true; foreach (var member in def.GetMembers ()) { if (member is IMethod && ((IMethod)member).FullName == "System.Object.Finalize") { @@ -1372,6 +1393,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } foreach (var u in n.Usings) { foreach (var type in u.Types) { + if (!lookup.IsAccessible(type, false)) + continue; + IType addType = typePred != null ? typePred(type) : type; if (addType != null) { string name = type.Name; @@ -1387,6 +1411,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } foreach (var type in n.Namespace.Types) { + if (!lookup.IsAccessible(type, false)) + continue; IType addType = typePred != null ? typePred(type) : type; if (addType != null) { var a2 = wrapper.AddType(addType, addType.Name); @@ -1686,7 +1712,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion string GetLineIndent(int lineNr) { var line = document.GetLineByNumber(lineNr); - for (int j = offset; j < line.EndOffset; j++) { + for (int j = line.Offset; j < line.EndOffset; j++) { char ch = document.GetCharAt(j); if (!char.IsWhiteSpace(ch)) { return document.GetText(line.Offset, j - line.Offset - 1); @@ -1744,7 +1770,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (!t.GetConstructors().Any(m => lookup.IsAccessible( m, isProtectedAllowed - ))) { + ) + )) { return null; } } @@ -1864,7 +1891,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion declarationBegin, method.DeclaringTypeDefinition, method - )); + ) + ); } return wrapper.Result; @@ -1912,7 +1940,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion bool foundMember = curType.GetMembers().Any(cm => SignatureComparer.Ordinal.Equals( cm, m - ) && cm.DeclaringTypeDefinition == curType.GetDefinition()); + ) && cm.DeclaringTypeDefinition == curType.GetDefinition() + ); if (foundMember) { continue; } @@ -1927,6 +1956,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion static void AddKeywords(CompletionDataWrapper wrapper, IEnumerable keywords) { foreach (string keyword in keywords) { + if (wrapper.Result.Any(data => data.DisplayText == keyword)) + continue; wrapper.AddCustom(keyword); } } @@ -1985,6 +2016,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion string delegateEndString = EolMarker + thisLineIndent + "}" + (addSemicolon ? ";" : ""); //bool containsDelegateData = completionList.Result.Any(d => d.DisplayText.StartsWith("delegate(")); if (addDefault) { + var oldDelegate = completionList.Result.FirstOrDefault(cd => cd.DisplayText == "delegate"); + if (oldDelegate != null) + completionList.Result.Remove(oldDelegate); completionList.AddCustom( "delegate", "Creates anonymous delegate.", @@ -2248,7 +2282,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion completionList.Result.Add(factory.CreateEntityCompletionData( field, typeString + "." + field.Name - )); + ) + ); } } DefaultCompletionString = typeString; @@ -2843,7 +2878,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion "seealso", "summary", "value" - }); + } + ); IEnumerable GetXmlDocumentationCompletionData() { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs index b5f9d8fa16..409112a298 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs @@ -1177,7 +1177,28 @@ class TestClass Assert.IsNotNull (provider.Find ("InnerEnumTest.TestEnum.B"), "enum 'InnerEnumTest.TestEnum.B' not found."); Assert.IsNotNull (provider.Find ("InnerEnumTest.TestEnum.C"), "enum 'InnerEnumTest.TestEnum.C' not found."); } - + + [Test()] + public void TestEnumInBinaryOperatorExpression () + { + CodeCompletionBugTests.CombinedProviderTest ( +@" +[Flags] +public enum TestEnum { A, B, C} + +class TestClass +{ + public void Foo () + { + $TestEnum test = TestEnum.A | T$ + } +}", provider => { + Assert.IsNotNull (provider.Find ("TestEnum"), "enum 'TestEnum' not found."); + Assert.IsNotNull (provider.Find ("TestEnum.A"), "enum 'TestEnum.A' not found."); + Assert.IsNotNull (provider.Find ("TestEnum.B"), "enum 'TestEnum.B' not found."); + Assert.IsNotNull (provider.Find ("TestEnum.C"), "enum 'TestEnum.C' not found."); + }); + } [Test()] public void TestPrimimitiveTypeCompletionString () diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs index f540932640..206aeae030 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs @@ -5246,5 +5246,34 @@ namespace EnumerationProblem }); } + /// + /// Bug 5191 - Creating extension method problem when typing "this" + /// + [Test()] + public void TestBug5191() + { + CombinedProviderTest( +@"using System; + +static class Ext +{ + $public static void Foo(t$ +} +", provider => { + Assert.IsNotNull(provider.Find("this"), "'this' not found."); + }); + + CombinedProviderTest( +@"using System; + +static class Ext +{ + $public static void Foo(int foo, t$ +} +", provider => { + Assert.IsNull(provider.Find("this"), "'this' found."); + }); + } + } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/DelegateContextTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/DelegateContextTests.cs index 7a75d65b30..7a66ddea77 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/DelegateContextTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/DelegateContextTests.cs @@ -72,6 +72,31 @@ public class Test Assert.IsNotNull(provider.Find("delegate")); }); } + + /// + /// Bug 5207 - [regression] delegate completion like event completion + /// + [Test()] + public void TestBug5207() + { + // note 'string bar = new Test ().ToString ()' would be valid. + CodeCompletionBugTests.CombinedProviderTest( +@"using System; + +public class Test +{ + Action foo; + + void TestFoo() + { + $foo = d$ + } +} +", provider => { + Assert.IsFalse(provider.AutoSelect); + Assert.IsNotNull(provider.Find("(arg1, arg2)")); + }); + } } }