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; // } } }