diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index d0a15a05f4..3aab57bea7 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -1249,13 +1249,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion AddKeywords(wrapper, parameterTypePredecessorKeywords); } } - AddKeywords(wrapper, primitiveTypesKeywords); - if (currentMember != null) { + if (currentMember != null && (node is IdentifierExpression || node is SimpleType) && (node.Parent is ExpressionStatement || node.Parent is ForeachStatement || node.Parent is UsingStatement)) { wrapper.AddCustom("var"); + wrapper.AddCustom("dynamic"); } wrapper.Result.AddRange(factory.CreateCodeTemplateCompletionData()); - if (node != null && node.Role == Roles.Argument) { var resolved = ResolveExpression(node.Parent); var invokeResult = resolved != null ? resolved.Item1 as CSharpInvocationResolveResult : null; @@ -2213,6 +2212,17 @@ namespace ICSharpCode.NRefactory.CSharp.Completion ); } } + + foreach (var method in resolveResult.Methods) { + if (parameter < method.Parameters.Count && method.Parameters [parameter].Type.Kind == TypeKind.Delegate) { + AutoSelect = false; + AutoCompleteEmptyMatch = false; + } + foreach (var p in method.Parameters) { + result.AddNamedParameterVariable(p); + } + } + if (!controlSpace) { if (addedEnums.Count + addedDelegates.Count == 0) { return Enumerable.Empty(); @@ -3034,7 +3044,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion "true", "false", "typeof", "checked", "unchecked", "from", "break", "checked", "unchecked", "const", "continue", "do", "finally", "fixed", "for", "foreach", "goto", "if", "lock", "return", "stackalloc", "switch", "throw", "try", "unsafe", - "using", "while", "yield", "dynamic", "var", "dynamic", + "using", "while", "yield", "catch" }; static string[] globalLevelKeywords = new string [] { diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs index 7de6312d0b..57e8c28348 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateMethodDeclarationAction.cs @@ -106,6 +106,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (guessedType.Kind != TypeKind.Delegate) yield break; var invocationMethod = guessedType.GetDelegateInvokeMethod(); + if (invocationMethod == null) + yield break; var state = context.GetResolverStateBefore(identifier); if (state.CurrentMember == null || state.CurrentTypeDefinition == null) yield break; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs index e175d257ed..234e17f261 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAstResolver.cs @@ -275,7 +275,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return true; } - return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression || node is ArrayInitializerExpression); + return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression); } } } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index 168bebca6b..ec47908926 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -41,8 +41,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public class CSharpResolver { static readonly ResolveResult ErrorResult = ErrorResolveResult.UnknownError; - static readonly ResolveResult DynamicResult = new ResolveResult(SpecialType.Dynamic); - static readonly ResolveResult NullResult = new ResolveResult(SpecialType.NullType); readonly ICompilation compilation; internal readonly CSharpConversions conversions; @@ -1381,7 +1379,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver foundInCache = cache.TryGetValue(identifier, out r); } } - if (!foundInCache) { + if (foundInCache) { + r = (r != null ? r.ShallowClone() : null); + } else { r = LookInCurrentType(identifier, typeArguments, lookupMode, parameterizeResultType); if (cache != null) { // also cache missing members (r==null) @@ -1398,9 +1398,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver r = LookInUsingScopeNamespace(null, compilation.RootNamespace, identifier, typeArguments, parameterizeResultType); } else { if (k == 0 && lookupMode != NameLookupMode.TypeInUsingDeclaration) { - if (!context.CurrentUsingScope.ResolveCache.TryGetValue(identifier, out r)) { + if (context.CurrentUsingScope.ResolveCache.TryGetValue(identifier, out r)) { + r = (r != null ? r.ShallowClone() : null); + } else { r = LookInCurrentUsingScope(identifier, typeArguments, false, false); - r = context.CurrentUsingScope.ResolveCache.GetOrAdd(identifier, r); + context.CurrentUsingScope.ResolveCache.TryAdd(identifier, r); } } else { r = LookInCurrentUsingScope(identifier, typeArguments, lookupMode == NameLookupMode.TypeInUsingDeclaration, parameterizeResultType); @@ -1477,7 +1479,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (!(isInUsingDeclaration && u == currentUsingScope)) { foreach (var pair in u.UsingAliases) { if (pair.Key == identifier) { - return pair.Value; + return pair.Value.ShallowClone(); } } } @@ -1589,7 +1591,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } if (target.Type.Kind == TypeKind.Dynamic) - return DynamicResult; + return new ResolveResult(SpecialType.Dynamic); MemberLookup lookup = CreateMemberLookup(lookupMode); ResolveResult result; @@ -1887,7 +1889,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: ยง7.6.5 if (target.Type.Kind == TypeKind.Dynamic) - return DynamicResult; + return new ResolveResult(SpecialType.Dynamic); MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; if (mgrr != null) { @@ -2297,7 +2299,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public ResolveResult ResolvePrimitive(object value) { if (value == null) { - return NullResult; + return new ResolveResult(SpecialType.NullType); } else { TypeCode typeCode = Type.GetTypeCode(value.GetType()); IType type = compilation.FindType(typeCode); diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs index e95d1d107f..4ebd96e594 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs @@ -51,13 +51,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver CancellationToken cancellationToken = default(CancellationToken)) { node = cu.GetNodeAt(location); - if (node == null) + if (node == null || node is ArrayInitializerExpression) return null; if (CSharpAstResolver.IsUnresolvableNode(node)) { if (node is Identifier) { node = node.Parent; } else if (node.NodeType == NodeType.Token) { if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) { + Console.WriteLine (2); // There's no other place where one could hover to see the indexer's tooltip, // so we need to resolve it when hovering over the '[' or ']'. // For constructor initializer, the same applies to the 'base'/'this' token. diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index 884560b128..84e8f74526 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -59,7 +59,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // The ResolveVisitor is also responsible for handling lambda expressions. static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError; - readonly ResolveResult voidResult; CSharpResolver resolver; /// Resolve result of the current LINQ query. @@ -112,13 +111,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.resolver = resolver; this.parsedFile = parsedFile; this.navigator = skipAllNavigator; - this.voidResult = new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void)); } internal void SetNavigator(IResolveVisitorNavigator navigator) { this.navigator = navigator ?? skipAllNavigator; } + + ResolveResult voidResult { + get { + return new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void)); + } + } #endregion #region ResetContext @@ -1594,7 +1598,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult IAstVisitor.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression) { if (resolverEnabled) { - return Resolve(typeReferenceExpression.Type); + return Resolve(typeReferenceExpression.Type).ShallowClone(); } else { Scan(typeReferenceExpression.Type); return null; @@ -2420,6 +2424,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal abstract AstNode BodyExpression { get; } internal abstract void EnforceMerge(ResolveVisitor parentVisitor); + + public override ResolveResult ShallowClone() + { + if (IsUndecided) + throw new NotSupportedException(); + return base.ShallowClone(); + } } void MergeUndecidedLambdas() @@ -3261,7 +3272,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver foreach (var clause in queryExpression.Clauses) { currentQueryResult = Resolve(clause); } - return currentQueryResult; + return WrapResult(currentQueryResult); } finally { currentQueryResult = oldQueryResult; cancellationToken = oldCancellationToken; diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs index 87c0ff5311..a5b191edbb 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/ResolverTest.cs @@ -55,6 +55,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } Dictionary resolvedNodes = new Dictionary(); + HashSet resolveResults = new HashSet(); HashSet nodesWithConversions = new HashSet(); public ResolveVisitorNavigationMode Scan(AstNode node) @@ -69,6 +70,9 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck resolvedNodes.Add(node, result); if (CSharpAstResolver.IsUnresolvableNode(node)) throw new InvalidOperationException("Resolved unresolvable node"); + if (!ParenthesizedExpression.ActsAsParenthesizedExpression(node)) + if (!resolveResults.Add(result)) + throw new InvalidOperationException("Duplicate resolve result"); if (result.IsError && !allowErrors) { Console.WriteLine("Compiler error at " + fileName + ":" + node.StartLocation + ": " + result); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs index 40082ea51f..213dea5038 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs @@ -81,7 +81,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions "class TestClass" + Environment.NewLine + "{" + Environment.NewLine + " int foo;" + Environment.NewLine + - "" + Environment.NewLine + " void Test ()" + Environment.NewLine + " {" + Environment.NewLine + " foo = 5;" + Environment.NewLine + @@ -109,7 +108,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions "class TestClass" + Environment.NewLine + "{" + Environment.NewLine + " int foo;" + Environment.NewLine + - "" + Environment.NewLine + " void Test ()" + Environment.NewLine + " {" + Environment.NewLine + " }" + Environment.NewLine + @@ -136,7 +134,6 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions "class TestClass" + Environment.NewLine + "{" + Environment.NewLine + " int foo;" + Environment.NewLine + - "" + Environment.NewLine + " TestClass (int foo)" + Environment.NewLine + " {" + Environment.NewLine + " this.foo = foo;" + Environment.NewLine + diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs index e1b601a8c2..54d99b2e35 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs @@ -82,10 +82,10 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions } }", @"class TestClass { - const string HelloWorld = ""Hello World""; + const string helloWorld = ""Hello World""; public void Hello () { - System.Console.WriteLine (HelloWorld); + System.Console.WriteLine (helloWorld); } }", 1); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs index 80cae089e7..a180ae9ca5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs @@ -4386,7 +4386,25 @@ namespace Test Assert.IsNotNull (provider.Find ("foo:"), "'foo:' not found."); }); } - + [Test()] + public void TestNamedParameters2 () + { + var provider = CreateCtrlSpaceProvider ( +@"class MyClass { + string Bar { get; set; } + + void MethodOne(string foo="""", string bar="""") + { + } + + void MethodTwo() { + MethodOne($$); + } +}"); + Assert.IsNotNull (provider.Find ("bar:"), "'bar:' not found."); + Assert.IsNotNull (provider.Find ("foo:"), "'foo:' not found."); + } + [Test()] public void TestNamedParametersConstructorCase () { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs index 708d643e9f..379b803f43 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs @@ -103,8 +103,8 @@ class TestClass { } } "; - var rr = Resolve(program); - Assert.AreEqual("System.Linq.Enumerable.Select", rr.Member.FullName); + var rr = Resolve(program); + Assert.IsTrue(rr.Conversion.IsIdentityConversion); Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName); Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName); } @@ -114,7 +114,7 @@ class TestClass { { string program = @"using System; class TestClass { static void M() { - $(from a in new XYZ() select a.ToUpper())$.ToString(); + (from a in new XYZ() $select a.ToUpper()$).ToString(); }} class XYZ { public int Select(Func f) { return 42; } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs index 814af48c4e..c5f19646fb 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs @@ -161,5 +161,23 @@ namespace Bug5114 "); Assert.AreEqual("HandleLongPressGesture", rr.MethodName); } + + [Test] + public void ArrayInitializer() + { + Assert.IsNull(ResolveAtLocation( +@"using System.Collections.Generic; +class Foo { + void Bar() + { + var o = new Dictionary () { + {1$, 2 }, + {1, 2 }, + {1, 2 }, + {1, 2 } + }; + } +}")); + } } } diff --git a/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs index c0991eef8d..e9998ad0ea 100644 --- a/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs @@ -75,6 +75,16 @@ namespace ICSharpCode.NRefactory.Semantics this.constantValue = constantValue; } + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue, bool isVirtualCall) + : base(returnType) + { + this.targetResult = targetResult; + this.member = member; + this.isConstant = isConstant; + this.constantValue = constantValue; + this.isVirtualCall = isVirtualCall; + } + public ResolveResult TargetResult { get { return targetResult; } } diff --git a/ICSharpCode.NRefactory/Semantics/ResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ResolveResult.cs index d73ecf6e41..fd8406efb8 100644 --- a/ICSharpCode.NRefactory/Semantics/ResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/ResolveResult.cs @@ -70,5 +70,10 @@ namespace ICSharpCode.NRefactory.Semantics { return DomRegion.Empty; } + + public virtual ResolveResult ShallowClone() + { + return (ResolveResult)MemberwiseClone(); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs index 5c630f9c09..c82a3a3017 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs @@ -63,7 +63,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation IType type = typeReference.Resolve(context); IEnumerable members; if (entityType == EntityType.Accessor) { - members = type.GetAccessors(m => m.Name == name && !m.IsExplicitInterfaceImplementation); + members = type.GetAccessors( + m => m.Name == name && !m.IsExplicitInterfaceImplementation, + GetMemberOptions.IgnoreInheritedMembers); } else if (entityType == EntityType.Method) { members = type.GetMethods( m => m.Name == name && m.EntityType == EntityType.Method