Browse Source

fix #498: Additional problems in DebuggerDotCompletion

fix #460: Debugger console: No completion inside constructors
pull/512/head
Siegfried Pammer 11 years ago
parent
commit
0c7ba630e4
  1. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 280
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  3. 253
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpTextEditorExtension.cs
  4. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs
  5. 49
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs
  6. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
  7. 3
      src/AddIns/Debugger/Debugger.AddIn/Breakpoints/BreakpointEditorPopup.xaml.cs
  8. 18
      src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs
  9. 5
      src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs
  10. 156
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs
  11. 2
      src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
  12. 5
      src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -91,6 +91,7 @@ @@ -91,6 +91,7 @@
<Compile Include="Src\CSharpSemanticHighlighterVisitor.cs">
<DependentUpon>CSharpSemanticHighlighter.cs</DependentUpon>
</Compile>
<Compile Include="Src\CSharpTextEditorExtension.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingOptionsContainer.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingPolicies.cs" />

280
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

@ -20,13 +20,18 @@ using System; @@ -20,13 +20,18 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Threading;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Project;
using CSharpBinding.Completion;
using CSharpBinding.FormattingStrategy;
using CSharpBinding.Refactoring;
@ -50,223 +55,98 @@ namespace CSharpBinding @@ -50,223 +55,98 @@ namespace CSharpBinding
this.container.AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), new Microsoft.CSharp.CSharpCodeProvider());
}
public override ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ICSharpCode.NRefactory.Editor.ITextSource fileContent)
public override ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
return new CSharpCompletionBinding(fileName, currentLocation, fileContent);
}
}
public class CSharpTextEditorExtension : ITextEditorExtension
{
ITextEditor editor;
IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders;
CodeManipulation codeManipulation;
CaretReferenceHighlightRenderer renderer;
CodeEditorFormattingOptionsAdapter options;
TextEditorOptions originalEditorOptions;
public void Attach(ITextEditor editor)
{
this.editor = editor;
inspectionManager = new IssueManager(editor);
codeManipulation = new CodeManipulation(editor);
renderer = new CaretReferenceHighlightRenderer(editor);
// Patch editor options (indentation) to project-specific settings
if (!editor.ContextActionProviders.IsReadOnly) {
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/SharpDevelop/ViewContent/TextEditor/C#/ContextActions", null);
editor.ContextActionProviders.AddRange(contextActionProviders);
}
// Create instance of options adapter and register it as service
var formattingPolicy = CSharpFormattingPolicies.Instance.GetProjectOptions(
SD.ProjectService.FindProjectContainingFile(editor.FileName));
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
options = new CodeEditorFormattingOptionsAdapter(textEditor.Options, editor.Options, formattingPolicy.OptionsContainer);
var textViewServices = textEditor.TextArea.TextView.Services;
// Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl.
textViewServices.RemoveService(typeof(ITextEditorOptions));
textViewServices.AddService(typeof(ITextEditorOptions), options);
// Set TextEditor's options to same object
originalEditorOptions = textEditor.Options;
textEditor.Options = options.TextEditorOptions;
}
if (context == null)
throw new ArgumentNullException("context");
string content = GeneratePartialClassContextStub(fileName, location, 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 new CSharpCompletionBinding(fileName, doc.GetLocation(caretOffset), doc.CreateSnapshot());
}
public void Detach()
static string GeneratePartialClassContextStub(FileName fileName, TextLocation location, ICodeContext context)
{
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
var textView = textEditor.TextArea.TextView;
// Unregister our ITextEditorOptions instance from editor
var optionsService = textView.GetService<ITextEditorOptions>();
if ((optionsService != null) && (optionsService == options))
textView.Services.RemoveService(typeof(ITextEditorOptions));
// Reset TextEditor options, too?
if ((textEditor.Options != null) && (textEditor.Options == options.TextEditorOptions))
textEditor.Options = originalEditorOptions;
}
codeManipulation.Dispose();
if (inspectionManager != null) {
inspectionManager.Dispose();
inspectionManager = null;
}
if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
var compilation = SD.ParserService.GetCompilationForFile(fileName);
var file = SD.ParserService.GetExistingUnresolvedFile(fileName);
if (compilation == null || file == null)
return "";
var unresolvedMember = file.GetMember(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));
}
}
}
renderer.Dispose();
options = null;
this.editor = null;
}
}
class CodeEditorFormattingOptionsAdapter : ITextEditorOptions, INotifyPropertyChanged
{
CSharpFormattingOptionsContainer container;
readonly TextEditorOptions avalonEditOptions;
readonly TextEditorOptions originalAvalonEditOptions;
readonly ITextEditorOptions originalSDOptions;
public CodeEditorFormattingOptionsAdapter(TextEditorOptions originalAvalonEditOptions, ITextEditorOptions originalSDOptions, CSharpFormattingOptionsContainer container)
{
if (originalAvalonEditOptions == null)
throw new ArgumentNullException("originalAvalonEditOptions");
if (originalSDOptions == null)
throw new ArgumentNullException("originalSDOptions");
if (container == null)
throw new ArgumentNullException("container");
this.originalAvalonEditOptions = originalAvalonEditOptions;
this.avalonEditOptions = new TextEditorOptions(originalAvalonEditOptions);
this.originalSDOptions = originalSDOptions;
this.container = container;
// Update overridden options once
UpdateOverriddenProperties();
CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated;
this.originalAvalonEditOptions.PropertyChanged += OnOrigAvalonOptionsPropertyChanged;
this.originalSDOptions.PropertyChanged += OnSDOptionsPropertyChanged;
}
void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e)
{
// Update editor options from changed policy
UpdateOverriddenProperties();
OnPropertyChanged("IndentationSize");
OnPropertyChanged("IndentationString");
OnPropertyChanged("ConvertTabsToSpaces");
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.LocalVariables.ToArray());
return WrapInType(unresolvedMember.DeclaringTypeDefinition, decl).ToString();
}
void UpdateOverriddenProperties()
static BlockStatement GenerateBodyFromContext(TypeSystemAstBuilder builder, IVariable[] variables)
{
avalonEditOptions.IndentationSize = container.GetEffectiveIndentationSize() ?? originalSDOptions.IndentationSize;
avalonEditOptions.ConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces() ?? originalSDOptions.ConvertTabsToSpaces;
var body = new BlockStatement();
foreach (var v in variables)
body.Statements.Add(new VariableDeclarationStatement(builder.ConvertType(v.Type), v.Name));
body.Statements.Add(new ExpressionStatement(new IdentifierExpression("$__Caret_Point__$")));
return body;
}
void OnOrigAvalonOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
static AstNode WrapInType(IUnresolvedTypeDefinition entity, EntityDeclaration decl)
{
if ((e.PropertyName != "IndentationSize") && (e.PropertyName != "IndentationString") && (e.PropertyName != "ConvertTabsToSpaces")) {
// Update values in our own TextEditorOptions instance
PropertyInfo propertyInfo = typeof(TextEditorOptions).GetProperty(e.PropertyName);
if (propertyInfo != null) {
propertyInfo.SetValue(avalonEditOptions, propertyInfo.GetValue(originalAvalonEditOptions));
if (entity == null)
return decl;
// Wrap decl in TypeDeclaration
decl = new TypeDeclaration {
ClassType = GetClassType(entity),
Modifiers = Modifiers.Partial,
Name = entity.Name,
Members = { decl }
};
if (entity.DeclaringTypeDefinition != null) {
// Handle nested types
return WrapInType(entity.DeclaringTypeDefinition, decl);
}
if (string.IsNullOrEmpty(entity.Namespace))
return decl;
return new NamespaceDeclaration(entity.Namespace) {
Members = {
decl
}
} else {
UpdateOverriddenProperties();
}
OnPropertyChanged(e.PropertyName);
};
}
void OnSDOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public TextEditorOptions TextEditorOptions
static ClassType GetClassType(IUnresolvedTypeDefinition entity)
{
get {
return avalonEditOptions;
}
}
#region Overridden properties
public int IndentationSize {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationSize;
}
}
public string IndentationString {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationString;
}
}
public bool ConvertTabsToSpaces {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.ConvertTabsToSpaces;
}
}
#endregion
#region Rest of ITextEditorOptions implementation
public bool AutoInsertBlockEnd {
get {
return originalSDOptions.AutoInsertBlockEnd;
}
}
public int VerticalRulerColumn {
get {
return originalSDOptions.VerticalRulerColumn;
switch (entity.Kind) {
case TypeKind.Interface:
return ClassType.Interface;
case TypeKind.Struct:
return ClassType.Struct;
default:
return ClassType.Class;
}
}
public bool UnderlineErrors {
get {
return originalSDOptions.UnderlineErrors;
}
}
public string FontFamily {
get {
return originalSDOptions.FontFamily;
}
}
public double FontSize {
get {
return originalSDOptions.FontSize;
}
}
#endregion
}
}

253
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpTextEditorExtension.cs

@ -0,0 +1,253 @@ @@ -0,0 +1,253 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using ICSharpCode.AvalonEdit;
using CSharpBinding.FormattingStrategy;
using CSharpBinding.Refactoring;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding
{
public class CSharpTextEditorExtension : ITextEditorExtension
{
ITextEditor editor;
IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders;
CodeManipulation codeManipulation;
CaretReferenceHighlightRenderer renderer;
CodeEditorFormattingOptionsAdapter options;
TextEditorOptions originalEditorOptions;
public void Attach(ITextEditor editor)
{
this.editor = editor;
inspectionManager = new IssueManager(editor);
codeManipulation = new CodeManipulation(editor);
renderer = new CaretReferenceHighlightRenderer(editor);
// Patch editor options (indentation) to project-specific settings
if (!editor.ContextActionProviders.IsReadOnly) {
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/SharpDevelop/ViewContent/TextEditor/C#/ContextActions", null);
editor.ContextActionProviders.AddRange(contextActionProviders);
}
// Create instance of options adapter and register it as service
var formattingPolicy = CSharpFormattingPolicies.Instance.GetProjectOptions(SD.ProjectService.FindProjectContainingFile(editor.FileName));
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
options = new CodeEditorFormattingOptionsAdapter(textEditor.Options, editor.Options, formattingPolicy.OptionsContainer);
var textViewServices = textEditor.TextArea.TextView.Services;
// Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl.
textViewServices.RemoveService(typeof(ITextEditorOptions));
textViewServices.AddService(typeof(ITextEditorOptions), options);
// Set TextEditor's options to same object
originalEditorOptions = textEditor.Options;
textEditor.Options = options.TextEditorOptions;
}
}
public void Detach()
{
var textEditor = editor.GetService<TextEditor>();
if (textEditor != null) {
var textView = textEditor.TextArea.TextView;
// Unregister our ITextEditorOptions instance from editor
var optionsService = textView.GetService<ITextEditorOptions>();
if ((optionsService != null) && (optionsService == options))
textView.Services.RemoveService(typeof(ITextEditorOptions));
// Reset TextEditor options, too?
if ((textEditor.Options != null) && (textEditor.Options == options.TextEditorOptions))
textEditor.Options = originalEditorOptions;
}
codeManipulation.Dispose();
if (inspectionManager != null) {
inspectionManager.Dispose();
inspectionManager = null;
}
if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
}
renderer.Dispose();
options = null;
this.editor = null;
}
}
class CodeEditorFormattingOptionsAdapter : ITextEditorOptions, INotifyPropertyChanged
{
CSharpFormattingOptionsContainer container;
readonly TextEditorOptions avalonEditOptions;
readonly TextEditorOptions originalAvalonEditOptions;
readonly ITextEditorOptions originalSDOptions;
public CodeEditorFormattingOptionsAdapter(TextEditorOptions originalAvalonEditOptions, ITextEditorOptions originalSDOptions, CSharpFormattingOptionsContainer container)
{
if (originalAvalonEditOptions == null)
throw new ArgumentNullException("originalAvalonEditOptions");
if (originalSDOptions == null)
throw new ArgumentNullException("originalSDOptions");
if (container == null)
throw new ArgumentNullException("container");
this.originalAvalonEditOptions = originalAvalonEditOptions;
this.avalonEditOptions = new TextEditorOptions(originalAvalonEditOptions);
this.originalSDOptions = originalSDOptions;
this.container = container;
// Update overridden options once
UpdateOverriddenProperties();
CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated;
this.originalAvalonEditOptions.PropertyChanged += OnOrigAvalonOptionsPropertyChanged;
this.originalSDOptions.PropertyChanged += OnSDOptionsPropertyChanged;
}
void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e)
{
// Update editor options from changed policy
UpdateOverriddenProperties();
OnPropertyChanged("IndentationSize");
OnPropertyChanged("IndentationString");
OnPropertyChanged("ConvertTabsToSpaces");
}
void UpdateOverriddenProperties()
{
avalonEditOptions.IndentationSize = container.GetEffectiveIndentationSize() ?? originalSDOptions.IndentationSize;
avalonEditOptions.ConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces() ?? originalSDOptions.ConvertTabsToSpaces;
}
void OnOrigAvalonOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if ((e.PropertyName != "IndentationSize") && (e.PropertyName != "IndentationString") && (e.PropertyName != "ConvertTabsToSpaces")) {
// Update values in our own TextEditorOptions instance
PropertyInfo propertyInfo = typeof(TextEditorOptions).GetProperty(e.PropertyName);
if (propertyInfo != null) {
propertyInfo.SetValue(avalonEditOptions, propertyInfo.GetValue(originalAvalonEditOptions));
}
} else {
UpdateOverriddenProperties();
}
OnPropertyChanged(e.PropertyName);
}
void OnSDOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ICSharpCode.AvalonEdit.TextEditorOptions TextEditorOptions
{
get {
return avalonEditOptions;
}
}
#region Overridden properties
public int IndentationSize {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationSize;
}
}
public string IndentationString {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.IndentationString;
}
}
public bool ConvertTabsToSpaces {
get {
// Get value from own TextEditorOptions instance
return avalonEditOptions.ConvertTabsToSpaces;
}
}
#endregion
#region Rest of ITextEditorOptions implementation
public bool AutoInsertBlockEnd {
get {
return originalSDOptions.AutoInsertBlockEnd;
}
}
public int VerticalRulerColumn {
get {
return originalSDOptions.VerticalRulerColumn;
}
}
public bool UnderlineErrors {
get {
return originalSDOptions.UnderlineErrors;
}
}
public string FontFamily {
get {
return originalSDOptions.FontFamily;
}
}
public double FontSize {
get {
return originalSDOptions.FontSize;
}
}
#endregion
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs

@ -24,10 +24,8 @@ using ICSharpCode.Core; @@ -24,10 +24,8 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;

49
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs

@ -17,17 +17,19 @@ @@ -17,17 +17,19 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Project;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using CSharpBinding.Parser;
namespace CSharpBinding.Completion
{
@ -35,7 +37,7 @@ namespace CSharpBinding.Completion @@ -35,7 +37,7 @@ namespace CSharpBinding.Completion
{
public readonly ITextEditor Editor;
public readonly IDocument Document;
public readonly CSharpFullParseInformation ParseInformation;
public readonly IList<string> ConditionalSymbols;
public readonly ICompilation Compilation;
public readonly IProjectContent ProjectContent;
public readonly CSharpTypeResolveContext TypeResolveContextAtCaret;
@ -56,7 +58,7 @@ namespace CSharpBinding.Completion @@ -56,7 +58,7 @@ namespace CSharpBinding.Completion
if (projectContent == null)
return null;
return new CSharpCompletionContext(editor, parseInfo, compilation, projectContent, editor.Document, editor.Caret.Location);
return new CSharpCompletionContext(editor, parseInfo.SyntaxTree.ConditionalSymbols, compilation, projectContent, editor.Document, parseInfo.UnresolvedFile, editor.Caret.Location);
}
public static CSharpCompletionContext Get(ITextEditor editor, ITextSource fileContent, TextLocation currentLocation, FileName fileName)
@ -64,33 +66,50 @@ namespace CSharpBinding.Completion @@ -64,33 +66,50 @@ namespace CSharpBinding.Completion
IDocument document = new ReadOnlyDocument(fileContent);
// Don't require the very latest parse information, an older cached version is OK.
var parseInfo = SD.ParserService.Parse(fileName, document) as CSharpFullParseInformation;
var parseInfo = SD.ParserService.GetCachedParseInformation(fileName) as CSharpFullParseInformation;
if (parseInfo == null) {
parseInfo = SD.ParserService.Parse(fileName) as CSharpFullParseInformation;
}
if (parseInfo == null)
return null;
ICompilation compilation = SD.ParserService.GetCompilationForFile(fileName);
var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
var project = SD.ProjectService.FindProjectContainingFile(fileName)as CSharpProject;
if (project == null)
return null;
var solutionSnapshot = SD.ParserService.GetCurrentSolutionSnapshot();
var projectContent = solutionSnapshot.GetProjectContent(project);
if (projectContent == null)
return null;
return new CSharpCompletionContext(editor, parseInfo, compilation, projectContent, document, currentLocation);
CSharpParser parser = new CSharpParser(project.CompilerSettings);
parser.GenerateTypeSystemMode = false;
SyntaxTree cu = parser.Parse(fileContent, Path.GetRandomFileName() + ".cs");
cu.Freeze();
CSharpUnresolvedFile unresolvedFile = cu.ToTypeSystem();
ICompilation compilation = projectContent.AddOrUpdateFiles(unresolvedFile).CreateCompilation(solutionSnapshot);
return new CSharpCompletionContext(editor, parseInfo.SyntaxTree.ConditionalSymbols, compilation, projectContent, document, unresolvedFile, currentLocation);
}
private CSharpCompletionContext(ITextEditor editor, CSharpFullParseInformation parseInfo, ICompilation compilation, IProjectContent projectContent, IDocument document, TextLocation caretLocation)
private CSharpCompletionContext(ITextEditor editor, IList<string> conditionalSymbols, ICompilation compilation, IProjectContent projectContent, IDocument document, CSharpUnresolvedFile unresolvedFile, TextLocation caretLocation)
{
Debug.Assert(editor != null);
Debug.Assert(parseInfo != null);
Debug.Assert(unresolvedFile != null);
Debug.Assert(compilation != null);
Debug.Assert(projectContent != null);
Debug.Assert(document != null);
this.Editor = editor;
this.Document = document;
this.ParseInformation = parseInfo;
this.ConditionalSymbols = conditionalSymbols;
this.Compilation = compilation;
this.ProjectContent = projectContent;
this.TypeResolveContextAtCaret = parseInfo.UnresolvedFile.GetTypeResolveContext(compilation, caretLocation);
this.CompletionContextProvider = new DefaultCompletionContextProvider(document, parseInfo.UnresolvedFile);
this.CompletionContextProvider.ConditionalSymbols.AddRange(parseInfo.SyntaxTree.ConditionalSymbols);
this.TypeResolveContextAtCaret = unresolvedFile.GetTypeResolveContext(compilation, caretLocation);
this.CompletionContextProvider = new DefaultCompletionContextProvider(document, unresolvedFile);
this.CompletionContextProvider.ConditionalSymbols.AddRange(conditionalSymbols);
}
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs

@ -148,7 +148,7 @@ namespace CSharpBinding.Completion @@ -148,7 +148,7 @@ namespace CSharpBinding.Completion
IEnumerable<ICompletionData> ICompletionDataFactory.CreatePreProcessorDefinesCompletionData()
{
return completionContext.ParseInformation.SyntaxTree.ConditionalSymbols.Select(def => new CompletionData(def));
return completionContext.ConditionalSymbols.Select(def => new CompletionData(def));
}
ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName, bool addForTypeCreation)

3
src/AddIns/Debugger/Debugger.AddIn/Breakpoints/BreakpointEditorPopup.xaml.cs

@ -41,7 +41,8 @@ namespace Debugger.AddIn.Breakpoints @@ -41,7 +41,8 @@ namespace Debugger.AddIn.Breakpoints
{
InitializeComponent();
this.DataContext = target;
condition.DebugContext = new DebuggerCompletionContext(target.FileName, target.Location);
condition.ContextFileName = target.FileName;
condition.ContextTextLocation = target.Location;
condition.FontFamily = new FontFamily(SD.EditorControlService.GlobalOptions.FontFamily);
condition.FontSize = SD.EditorControlService.GlobalOptions.FontSize;
if (target.Condition == null)

18
src/AddIns/Debugger/Debugger.AddIn/Pads/AutoCompleteTextBox.cs

@ -64,7 +64,8 @@ namespace Debugger.AddIn.Pads.Controls @@ -64,7 +64,8 @@ namespace Debugger.AddIn.Pads.Controls
set { SetValue(IsEditableProperty, value); }
}
public DebuggerCompletionContext DebugContext { get; set; }
public FileName ContextFileName { get; set; }
public TextLocation ContextTextLocation { get; set; }
static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
@ -127,20 +128,15 @@ namespace Debugger.AddIn.Pads.Controls @@ -127,20 +128,15 @@ namespace Debugger.AddIn.Pads.Controls
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 (frame != null) {
ContextFileName = new FileName(frame.NextStatement.Filename);
ContextTextLocation = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn);
}
if (context == null) return;
var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), context);
if (ContextFileName == null) return;
var binding = DebuggerDotCompletion.PrepareDotCompletion(editor.Text.Substring(0, editor.CaretOffset), ContextFileName, ContextTextLocation, SD.ParserService.ResolveContext(ContextFileName, ContextTextLocation));
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;

5
src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs

@ -86,10 +86,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -86,10 +86,11 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
void ShowDotCompletion(StackFrame frame, string currentText)
{
var binding = DebuggerDotCompletion.PrepareDotCompletion(currentText, new DebuggerCompletionContext(frame));
var fileName = new ICSharpCode.Core.FileName(frame.NextStatement.Filename);
var textLocation = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn);
var binding = DebuggerDotCompletion.PrepareDotCompletion(currentText, fileName, textLocation, SD.ParserService.ResolveContext(fileName, textLocation));
if (binding == null) return;
binding.HandleKeyPressed(console.TextEditor, '.');
SD.ParserService.ParseFileAsync(new ICSharpCode.Core.FileName(frame.NextStatement.Filename)).FireAndForget();
}
protected override ToolBar BuildToolBar()

156
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerDotCompletion.cs

@ -41,162 +41,12 @@ namespace Debugger.AddIn.Pads.Controls @@ -41,162 +41,12 @@ namespace Debugger.AddIn.Pads.Controls
return !errors.Any();
}
public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, DebuggerCompletionContext context)
public static ICodeCompletionBinding PrepareDotCompletion(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{
var lang = SD.LanguageService.GetLanguageByFileName(context.FileName);
var lang = SD.LanguageService.GetLanguageByFileName(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 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 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 AstNode WrapInType(IUnresolvedTypeDefinition entity, EntityDeclaration decl)
{
if (entity == null)
return decl;
// Wrap decl in TypeDeclaration
decl = new TypeDeclaration {
ClassType = GetClassType(entity),
Modifiers = Modifiers.Partial,
Name = entity.Name,
Members = { decl }
};
if (entity.DeclaringTypeDefinition != null) {
// Handle nested types
return WrapInType(entity.DeclaringTypeDefinition, decl);
}
if (string.IsNullOrEmpty(entity.Namespace))
return decl;
return new NamespaceDeclaration(entity.Namespace) {
Members = {
decl
}
};
}
static ClassType GetClassType(IUnresolvedTypeDefinition entity)
{
switch (entity.Kind) {
case TypeKind.Interface:
return ClassType.Interface;
case TypeKind.Struct:
return ClassType.Struct;
default:
return ClassType.Class;
}
}
}
public class LocalVariable
{
readonly IType type;
public IType Type {
get {
return type;
}
}
readonly string name;
public string Name {
get {
return name;
}
}
public LocalVariable(IType type, string name)
{
this.type = type;
this.name = name;
}
}
public class DebuggerCompletionContext
{
readonly FileName fileName;
TextLocation location;
readonly LocalVariable[] variables;
public DebuggerCompletionContext(StackFrame frame)
{
fileName = new FileName(frame.NextStatement.Filename);
location = new TextLocation(frame.NextStatement.StartLine, frame.NextStatement.StartColumn);
variables = frame.GetLocalVariables().Select(v => new LocalVariable(v.Type, v.Name)).ToArray();
}
public DebuggerCompletionContext(FileName fileName, TextLocation location)
{
this.fileName = fileName;
this.location = location;
this.variables = SD.ParserService.ResolveContext(fileName, location)
.LocalVariables.Select(v => new LocalVariable(v.Type, v.Name)).ToArray();
}
public FileName FileName {
get {
return fileName;
}
}
public TextLocation Location {
get {
return location;
}
}
public LocalVariable[] Variables {
get {
return variables;
}
return lang.CreateCompletionBinding(expressionToComplete, fileName, location, context);
}
}
}

2
src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs

@ -75,7 +75,7 @@ namespace ICSharpCode.SharpDevelop @@ -75,7 +75,7 @@ namespace ICSharpCode.SharpDevelop
}
}
public virtual ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ITextSource fileContent)
public virtual ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context)
{
throw new NotSupportedException();
}

5
src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
@ -62,8 +63,8 @@ namespace ICSharpCode.SharpDevelop @@ -62,8 +63,8 @@ namespace ICSharpCode.SharpDevelop
}
/// <summary>
/// Creates a completion binding which works with a fileName and a location as context.
/// Creates a completion binding for a given expression and context.
/// </summary>
ICodeCompletionBinding CreateCompletionBinding(FileName fileName, TextLocation currentLocation, ITextSource fileContent);
ICodeCompletionBinding CreateCompletionBinding(string expressionToComplete, FileName fileName, TextLocation location, ICodeContext context);
}
}

Loading…
Cancel
Save