diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index 8b1572ed02..1028742e0c 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -162,9 +162,10 @@ namespace CSharpBinding { CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName); int cursor = editor.ActiveTextAreaControl.Caret.Offset; - ExpressionContext context = ef.FindExpression(editor.Document.GetText(0, cursor) + " T.", cursor + 2).Context; - if (context.IsObjectCreation) { - editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(context), ' '); + ExpressionResult expressionResult = ef.FindExpression(editor.Document.GetText(0, cursor), cursor - 1); + LoggingService.Debug("ShowNewCompletion: expression is " + expressionResult); + if (expressionResult.Context.IsObjectCreation) { + editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(expressionResult.Context), ' '); return true; } return false; diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt index 2af54de1ae..e832cefa31 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt +++ b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt @@ -203,7 +203,7 @@ ExpressionStart("base", "delegate", "false", "new", "null", "sizeof", "this", "t ExpressionContent("as", "is", "out", "ref", "in") # interfaces cannot have inner classes etc., the only keyword (expect for type names) that may appear in them is "event" InterfaceLevel("event") -TypeLevel(@KCCTypeDeclarationStart, @KCCMemberVisibilityModifiers, "const", "event", "explicit", "extern", "fixed", "implicit", "operator", "override", "readonly", "virtual", "volatile") +TypeLevel(@KCCTypeDeclarationStart, @KCCMemberVisibilityModifiers, "const", "event", "explicit", "extern", "fixed", "implicit", "new", "operator", "override", "readonly", "virtual", "volatile") StatementStart(@ExpressionStart, @ExpressionContent, "break", "case", "catch", "checked", "unchecked", "const", "continue", "default", "do", "else", "finally", "fixed", "for", "foreach", "goto", "if", "lock", "return", "stackalloc", "switch", "throw", "try", "unsafe", "using", "while", "yield") QueryExpressionClauseStart("from", "let", "where", "join", "orderby", "group", "select") InPropertyDeclaration(@KCCMemberVisibilityModifiers, "get", "set") diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs index 1075857763..6d4911400f 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs @@ -185,7 +185,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp public static BitArray ExpressionStart = NewSet(Base, Delegate, False, New, Null, Sizeof, This, True, Typeof, Checked, Unchecked, From); public static BitArray ExpressionContent = NewSet(As, Is, Out, Ref, In); public static BitArray InterfaceLevel = NewSet(Event); - public static BitArray TypeLevel = NewSet(Public, Internal, Class, Interface, Struct, Enum, Delegate, Abstract, Sealed, Static, Unsafe, Partial, Protected, Private, Public, Internal, Const, Event, Explicit, Extern, Fixed, Implicit, Operator, Override, Readonly, Virtual, Volatile); + public static BitArray TypeLevel = NewSet(Public, Internal, Class, Interface, Struct, Enum, Delegate, Abstract, Sealed, Static, Unsafe, Partial, Protected, Private, Public, Internal, Const, Event, Explicit, Extern, Fixed, Implicit, New, Operator, Override, Readonly, Virtual, Volatile); public static BitArray StatementStart = NewSet(Base, Delegate, False, New, Null, Sizeof, This, True, Typeof, Checked, Unchecked, From, As, Is, Out, Ref, In, Break, Case, Catch, Checked, Unchecked, Const, Continue, Default, Do, Else, Finally, Fixed, For, Foreach, Goto, If, Lock, Return, Stackalloc, Switch, Throw, Try, Unsafe, Using, While, Yield); public static BitArray QueryExpressionClauseStart = NewSet(From, Let, Where, Join, Orderby, Group, Select); public static BitArray InPropertyDeclaration = NewSet(Protected, Private, Public, Internal, Get, Set); diff --git a/src/Main/Base/Test/CSharpExpressionFinderTests.cs b/src/Main/Base/Test/CSharpExpressionFinderTests.cs index 8af2ece4b9..c20e248bf9 100644 --- a/src/Main/Base/Test/CSharpExpressionFinderTests.cs +++ b/src/Main/Base/Test/CSharpExpressionFinderTests.cs @@ -285,6 +285,33 @@ class Main { FindExpr(propertyProgram, "\t/* in setter", null, ExpressionContext.MethodBody); FindExpr(propertyProgram, "\t/* still in prop", null, ExpressionContext.PropertyDeclaration); } + + [Test] + public void FindObjectCreationContextForNewKeywordCompletion() + { + const string program = @"using System; using System.Text; +class Main { + void M() { + StringBuilder b = new"; + + ExpressionResult result = ef.FindExpression(program, program.Length - 1); + Assert.AreEqual(ExpressionContext.ObjectCreation.ToString(), result.Context.ToString()); + } + + [Test] + public void ExpressionContextInFieldInitializer() + { + const string program = @"using System; using System.Collections.Generic; +class Main { + int field1 = 1; + int field2 = StaticMethod( 2); + int field3 = MakeArray()[ 3]; +}"; + FindExpr(program, " 1", null, ExpressionContext.Default); + FindExpr(program, " 2", null, ExpressionContext.Default); + FindFull(program, "taticMethod", "StaticMethod( 2)", ExpressionContext.Default); + FindExpr(program, " 3", null, ExpressionContext.Default); + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs index b9911f48e8..300adf913f 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs @@ -184,6 +184,13 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp case FrameType.Event: this.childType = FrameType.Statements; break; + case FrameType.TypeDecl: + if (state == FrameState.Initializer) { + this.childType = FrameType.Expression; + break; + } else { + goto default; + } default: this.childType = this.type; break; @@ -291,7 +298,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp if (frame.lastExpressionStart.IsEmpty && token.kind == Tokens.OpenParenthesis) frame.lastExpressionStart = token.Location; frame = new Frame(frame); - frame.parent.childType = frame.parent.type; + frame.parent.ResetChildType(); frame.bracketType = '('; break; case Tokens.CloseParenthesis: @@ -355,7 +362,9 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp frame.SetExpectedType(projectContent.SystemTypes.Exception); break; case Tokens.New: - frame.SetContext(ExpressionContext.TypeDerivingFrom(frame.expectedType, true)); + if (frame.type == FrameType.Statements || frame.type == FrameType.Expression) { + frame.SetContext(ExpressionContext.TypeDerivingFrom(frame.expectedType, true)); + } break; case Tokens.Namespace: frame.SetContext(ExpressionContext.IdentifierExpected); @@ -370,6 +379,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp } else if (frame.type == FrameType.TypeDecl) { frame.SetContext(ExpressionContext.Default); frame.state = FrameState.Initializer; + frame.ResetChildType(); break; } else { goto default;