static string GeneratePartialClassContextStub(DebuggerCompletionContext context)
		{
			var compilation = SD.ParserService.GetCompilationForFile(context.FileName);
			var file = SD.ParserService.GetExistingUnresolvedFile(context.FileName);
			if (compilation == null || file == null)
				return "";
			var unresolvedMember = file.GetMember(context.Location);
			if (unresolvedMember == null)
				return "";
			var member = unresolvedMember.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly));
			if (member == null)
				return "";
			var builder = new TypeSystemAstBuilder();
			MethodDeclaration decl;
			if (unresolvedMember is IMethod) {
				// If it's a method, convert it directly (including parameters + type parameters)
				decl = (MethodDeclaration)builder.ConvertEntity(member);
			} else {
				// Otherwise, create a method anyways, and copy the parameters
				decl = new MethodDeclaration();
				if (member is IParameterizedMember) {
					foreach (var p in ((IParameterizedMember)member).Parameters) {
						decl.Parameters.Add(builder.ConvertParameter(p));
					}
				}
			}
			decl.Name = "__DebuggerStub__";
			decl.ReturnType = builder.ConvertType(member.ReturnType);
			decl.Modifiers = unresolvedMember.IsStatic ? Modifiers.Static : Modifiers.None;
			// Make the method look like an explicit interface implementation so that it doesn't appear in CC
			decl.PrivateImplementationType = new SimpleType("__DummyType__");
			decl.Body = GenerateBodyFromContext(builder, context);
			return WrapInType(unresolvedMember.DeclaringTypeDefinition, decl).ToString();
		}
 static void GenerateBodyFromContext(TypeSystemAstBuilder builder, DebuggerCompletionContext context, MethodDeclaration methodDeclaration)
 {
     methodDeclaration.Body = new BlockStatement();
     foreach (var v in context.Variables)
     {
         methodDeclaration.Body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
     }
     methodDeclaration.Body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
 }
		public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context)
		{
			var lang = SD.LanguageService.GetLanguageByFileName(context.FileName);
			if (lang == null)
				return null;
			string content = GeneratePartialClassContextStub(context);
			const string caretPoint = "$__Caret_Point__$;";
			int caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length;
			SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$"));
			var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete));
			return lang.CreateCompletionBinding(context.FileName, doc.GetLocation(caretOffset), doc.CreateSnapshot());
		}
        static string GeneratePartialClassContextStub(DebuggerCompletionContext context)
        {
            var compilation = SD.ParserService.GetCompilationForFile(context.FileName);
            var file        = SD.ParserService.GetExistingUnresolvedFile(context.FileName);

            if (compilation == null || file == null)
            {
                return("");
            }
            var member = file.GetMember(context.Location);

            if (member == null)
            {
                return("");
            }
            var builder            = new TypeSystemAstBuilder();
            EntityDeclaration decl = builder.ConvertEntity(member.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)));

            decl.Name       = "__DebuggerStub_" + decl.Name;
            decl.Modifiers &= (Modifiers.Static);
            switch (member.SymbolKind)
            {
            case SymbolKind.Property:
                break;

            case SymbolKind.Indexer:
                break;

            case SymbolKind.Event:
                break;

            case SymbolKind.Method:
                GenerateBodyFromContext(builder, context, (MethodDeclaration)decl);
                break;

            case SymbolKind.Operator:
                break;

            case SymbolKind.Constructor:
                break;

            case SymbolKind.Destructor:
                break;

            case SymbolKind.Accessor:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(WrapInType(member.DeclaringTypeDefinition, decl.ToString()));
        }
        static string GeneratePartialClassContextStub(DebuggerCompletionContext context)
        {
            var compilation = SD.ParserService.GetCompilationForFile(context.FileName);
            var file        = SD.ParserService.GetExistingUnresolvedFile(context.FileName);

            if (compilation == null || file == null)
            {
                return("");
            }
            var unresolvedMember = file.GetMember(context.Location);

            if (unresolvedMember == null)
            {
                return("");
            }
            var member = unresolvedMember.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly));

            if (member == null)
            {
                return("");
            }
            var builder = new TypeSystemAstBuilder();
            MethodDeclaration decl;

            if (unresolvedMember is IMethod)
            {
                // If it's a method, convert it directly (including parameters + type parameters)
                decl = (MethodDeclaration)builder.ConvertEntity(member);
            }
            else
            {
                // Otherwise, create a method anyways, and copy the parameters
                decl = new MethodDeclaration();
                if (member is IParameterizedMember)
                {
                    foreach (var p in ((IParameterizedMember)member).Parameters)
                    {
                        decl.Parameters.Add(builder.ConvertParameter(p));
                    }
                }
            }
            decl.Name       = "__DebuggerStub__";
            decl.ReturnType = builder.ConvertType(member.ReturnType);
            decl.Modifiers  = unresolvedMember.IsStatic ? Modifiers.Static : Modifiers.None;
            // Make the method look like an explicit interface implementation so that it doesn't appear in CC
            decl.PrivateImplementationType = new SimpleType("__DummyType__");
            decl.Body = GenerateBodyFromContext(builder, context);
            return(WrapInType(unresolvedMember.DeclaringTypeDefinition, decl).ToString());
        }
        void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
        {
            if (e.Text == ".")
            {
                DebuggerCompletionContext context = null;
                StackFrame frame = WindowsDebugger.CurrentStackFrame;
                if (frame == null)
                {
                    if (DebugContext != null)
                    {
                        context = DebugContext;
                    }
                }
                else
                {
                    context = new DebuggerCompletionContext(frame);
                }
                if (context == null)
                {
                    return;
                }
                var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context);
                if (binding == null)
                {
                    return;
                }
                binding.HandleKeyPressed(editorAdapter, '.');
                SD.ParserService.ParseFileAsync(context.FileName).FireAndForget();
            }
            else
            {
                // TODO : implement automated error checking CSharpParser.ParseExpression does not report useful error messages.
//				Error[] errors;
//				if (!DebuggerDotCompletion.CheckSyntax(Text, out errors)) {
//					StringBuilder output = new StringBuilder();
//					foreach (var error in errors) {
//						output.AppendLine(error.Message + " at " + error.Region.Begin);
//					}
//					messageView.Content = output.ToString();
//					messageView.IsOpen = true;
//				} else {
//					messageView.IsOpen = false;
//				}
            }
        }
		static string GeneratePartialClassContextStub(DebuggerCompletionContext context)
		{
			var compilation = SD.ParserService.GetCompilationForFile(context.FileName);
			var file = SD.ParserService.GetExistingUnresolvedFile(context.FileName);
			if (compilation == null || file == null)
				return "";
			var member = file.GetMember(context.Location);
			if (member == null)
				return "";
			var builder = new TypeSystemAstBuilder();
			EntityDeclaration decl = builder.ConvertEntity(member.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)));
			decl.Name = "__DebuggerStub_" + decl.Name;
			decl.Modifiers &= (Modifiers.Static);
			switch (member.SymbolKind) {
				case SymbolKind.Property:
					break;
				case SymbolKind.Indexer:
					break;
				case SymbolKind.Event:
					break;
				case SymbolKind.Method:
					GenerateBodyFromContext(builder, context, (MethodDeclaration)decl);
					break;
				case SymbolKind.Operator:
					break;
				case SymbolKind.Constructor:
					break;
				case SymbolKind.Destructor:
					break;
				case SymbolKind.Accessor:
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}
			return WrapInType(member.DeclaringTypeDefinition, decl.ToString());
		}
        public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context)
        {
            var lang = SD.LanguageService.GetLanguageByFileName(context.FileName);

            if (lang == null)
            {
                return(null);
            }
            string       content     = GeneratePartialClassContextStub(context);
            const string caretPoint  = "$__Caret_Point__$;";
            int          caretOffset = content.IndexOf(caretPoint, StringComparison.Ordinal) + expressionToComplete.Length;

            SD.Log.DebugFormatted("context used for dot completion: {0}", content.Replace(caretPoint, "$" + expressionToComplete + "|$"));
            var doc = new ReadOnlyDocument(content.Replace(caretPoint, expressionToComplete));

            return(lang.CreateCompletionBinding(context.FileName, doc.GetLocation(caretOffset), doc.CreateSnapshot()));
        }
		static BlockStatement GenerateBodyFromContext(TypeSystemAstBuilder builder, DebuggerCompletionContext context)
		{
			var body = new BlockStatement();
			foreach (var v in context.Variables)
				body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
			body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
			return body;
		}
		static void GenerateBodyFromContext(TypeSystemAstBuilder builder, DebuggerCompletionContext context, MethodDeclaration methodDeclaration)
		{
			methodDeclaration.Body = new BlockStatement();
			foreach (var v in context.Variables)
				methodDeclaration.Body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
			methodDeclaration.Body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
		}
		void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
		{
			if (e.Text == ".") {
				DebuggerCompletionContext context = null;
				StackFrame frame = WindowsDebugger.CurrentStackFrame;
				if (frame == null) {
					if (DebugContext != null) {
						context = DebugContext;
					}
				} else {
					context = new DebuggerCompletionContext(frame);
				}
				if (context == null) return;
				var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context);
				if (binding == null) return;
				binding.HandleKeyPressed(editorAdapter, '.');
				SD.ParserService.ParseFileAsync(context.FileName).FireAndForget();
			} else {
				// TODO : implement automated error checking CSharpParser.ParseExpression does not report useful error messages.
//				Error[] errors;
//				if (!DebuggerDotCompletion.CheckSyntax(Text, out errors)) {
//					StringBuilder output = new StringBuilder();
//					foreach (var error in errors) {
//						output.AppendLine(error.Message + " at " + error.Region.Begin);
//					}
//					messageView.Content = output.ToString();
//					messageView.IsOpen = true;
//				} else {
//					messageView.IsOpen = false;
//				}
			}
		}