Browse Source

Highlight active parameter in method insight.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
5dacab6a80
  1. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 41
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs
  3. 56
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionContext.cs
  4. 37
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
  5. 108
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs
  6. 110
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs
  7. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  8. 14
      src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs

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

@ -66,7 +66,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" /> <Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\Completion\CSharpCompletionContext.cs" />
<Compile Include="Src\Completion\CSharpInsightItem.cs" /> <Compile Include="Src\Completion\CSharpInsightItem.cs" />
<Compile Include="Src\Completion\CSharpMethodInsight.cs" />
<Compile Include="Src\Completion\OverrideCompletionData.cs" /> <Compile Include="Src\Completion\OverrideCompletionData.cs" />
<Compile Include="Src\Completion\SegmentTrackingOutputFormatter.cs" /> <Compile Include="Src\Completion\SegmentTrackingOutputFormatter.cs" />
<Compile Include="Src\Refactoring\InsertionPoint.cs" /> <Compile Include="Src\Refactoring\InsertionPoint.cs" />

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

@ -4,15 +4,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding.Completion namespace CSharpBinding.Completion
{ {
@ -38,27 +35,17 @@ namespace CSharpBinding.Completion
bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace) bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace)
{ {
// Don't require the very latest parse information, an older cached version is OK. var completionContext = CSharpCompletionContext.Get(editor);
var parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation; if (completionContext == null)
if (parseInfo == null) {
parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo == null)
return false;
}
ICompilation compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
if (projectContent == null)
return false; return false;
var completionContextProvider = new DefaultCompletionContextProvider(editor.Document, parseInfo.ParsedFile); var completionFactory = new CSharpCompletionDataFactory(this, editor, completionContext.TypeResolveContextAtCaret);
var typeResolveContext = parseInfo.ParsedFile.GetTypeResolveContext(compilation, editor.Caret.Location);
var completionFactory = new CSharpCompletionDataFactory(typeResolveContext);
CSharpCompletionEngine cce = new CSharpCompletionEngine( CSharpCompletionEngine cce = new CSharpCompletionEngine(
editor.Document, editor.Document,
completionContextProvider, completionContext.CompletionContextProvider,
completionFactory, completionFactory,
projectContent, completionContext.ProjectContent,
typeResolveContext completionContext.TypeResolveContextAtCaret
); );
cce.FormattingPolicy = FormattingOptionsFactory.CreateSharpDevelop(); cce.FormattingPolicy = FormattingOptionsFactory.CreateSharpDevelop();
@ -102,15 +89,15 @@ namespace CSharpBinding.Completion
// Method Insight // Method Insight
var pce = new CSharpParameterCompletionEngine( var pce = new CSharpParameterCompletionEngine(
editor.Document, editor.Document,
completionContextProvider, completionContext.CompletionContextProvider,
completionFactory, completionFactory,
projectContent, completionContext.ProjectContent,
typeResolveContext completionContext.TypeResolveContextAtCaret
); );
var provider = pce.GetParameterDataProvider(editor.Caret.Offset, completionChar) as CSharpParameterDataProvider; var newInsight = pce.GetParameterDataProvider(editor.Caret.Offset, completionChar) as CSharpMethodInsight;
if (provider != null && provider.items.Count > 0) { if (newInsight != null && newInsight.items.Count > 0) {
var insightWindow = editor.ShowInsightWindow(provider.items); newInsight.UpdateHighlightedParameter(pce);
insightWindow.StartOffset = provider.StartOffset; newInsight.Show();
return true; return true;
} }
} }

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

@ -0,0 +1,56 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Diagnostics;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding.Completion
{
sealed class CSharpCompletionContext
{
public readonly ITextEditor Editor;
public readonly CSharpFullParseInformation ParseInformation;
public readonly ICompilation Compilation;
public readonly IProjectContent ProjectContent;
public readonly CSharpTypeResolveContext TypeResolveContextAtCaret;
public readonly ICompletionContextProvider CompletionContextProvider;
public static CSharpCompletionContext Get(ITextEditor editor)
{
// Don't require the very latest parse information, an older cached version is OK.
var parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation;
if (parseInfo == null) {
parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
}
if (parseInfo == null)
return null;
ICompilation compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
var projectContent = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
if (projectContent == null)
return null;
return new CSharpCompletionContext(editor, parseInfo, compilation, projectContent);
}
private CSharpCompletionContext(ITextEditor editor, CSharpFullParseInformation parseInfo, ICompilation compilation, IProjectContent projectContent)
{
Debug.Assert(editor != null);
Debug.Assert(parseInfo != null);
Debug.Assert(compilation != null);
Debug.Assert(projectContent != null);
this.Editor = editor;
this.ParseInformation = parseInfo;
this.Compilation = compilation;
this.ProjectContent = projectContent;
this.TypeResolveContextAtCaret = parseInfo.ParsedFile.GetTypeResolveContext(compilation, editor.Caret.Location);
this.CompletionContextProvider = new DefaultCompletionContextProvider(editor.Document, parseInfo.ParsedFile);
}
}
}

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

@ -3,27 +3,36 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding.Completion namespace CSharpBinding.Completion
{ {
class CSharpCompletionDataFactory : ICompletionDataFactory, IParameterCompletionDataFactory sealed class CSharpCompletionDataFactory : ICompletionDataFactory, IParameterCompletionDataFactory
{ {
readonly CSharpCompletionBinding binding;
readonly ITextEditor editor;
readonly CSharpTypeResolveContext contextAtCaret; readonly CSharpTypeResolveContext contextAtCaret;
public CSharpCompletionDataFactory(CSharpTypeResolveContext contextAtCaret) public CSharpCompletionDataFactory(CSharpCompletionBinding binding, ITextEditor editor, CSharpTypeResolveContext contextAtCaret)
{ {
if (contextAtCaret == null) Debug.Assert(binding != null);
throw new ArgumentNullException("contextAtCaret"); Debug.Assert(editor != null);
Debug.Assert(contextAtCaret != null);
this.binding = binding;
this.editor = editor;
this.contextAtCaret = contextAtCaret; this.contextAtCaret = contextAtCaret;
} }
#region ICompletionDataFactory implementation
public ICompletionData CreateEntityCompletionData(IUnresolvedEntity entity) public ICompletionData CreateEntityCompletionData(IUnresolvedEntity entity)
{ {
return new CompletionData(entity.Name) { return new CompletionData(entity.Name) {
@ -81,7 +90,7 @@ namespace CSharpBinding.Completion
public ICompletionData CreateVariableCompletionData(IVariable variable) public ICompletionData CreateVariableCompletionData(IVariable variable)
{ {
return new CompletionData(variable.Name) { return new CompletionData(variable.Name) {
Image = ClassBrowserIconService.LocalVariable Image = ClassBrowserIconService.LocalVariable
}; };
} }
@ -115,33 +124,37 @@ namespace CSharpBinding.Completion
{ {
yield break; yield break;
} }
#endregion
#region IParameterCompletionDataFactory implementation #region IParameterCompletionDataFactory implementation
IParameterDataProvider CreateMethodDataProvider(int startOffset, IEnumerable<IParameterizedMember> methods)
{
return new CSharpMethodInsight(binding, editor, startOffset, from m in methods where m != null select new CSharpInsightItem(m));
}
IParameterDataProvider IParameterCompletionDataFactory.CreateConstructorProvider(int startOffset, IType type) IParameterDataProvider IParameterCompletionDataFactory.CreateConstructorProvider(int startOffset, IType type)
{ {
IAmbience ambience = AmbienceService.GetCurrentAmbience(); return CreateMethodDataProvider(startOffset, type.GetConstructors());
return new CSharpParameterDataProvider(startOffset, type.GetConstructors().Select(m => new CSharpInsightItem(m, ambience)));
} }
IParameterDataProvider IParameterCompletionDataFactory.CreateMethodDataProvider(int startOffset, IEnumerable<IMethod> methods) IParameterDataProvider IParameterCompletionDataFactory.CreateMethodDataProvider(int startOffset, IEnumerable<IMethod> methods)
{ {
IAmbience ambience = AmbienceService.GetCurrentAmbience(); return CreateMethodDataProvider(startOffset, methods);
return new CSharpParameterDataProvider(startOffset, methods.Select(m => new CSharpInsightItem(m, ambience)));
} }
IParameterDataProvider IParameterCompletionDataFactory.CreateDelegateDataProvider(int startOffset, IType type) IParameterDataProvider IParameterCompletionDataFactory.CreateDelegateDataProvider(int startOffset, IType type)
{ {
return new CSharpParameterDataProvider(startOffset, Enumerable.Empty<CSharpInsightItem>()); return CreateMethodDataProvider(startOffset, new[] { type.GetDelegateInvokeMethod() });
} }
IParameterDataProvider IParameterCompletionDataFactory.CreateIndexerParameterDataProvider(int startOffset, IType type, AstNode resolvedNode) IParameterDataProvider IParameterCompletionDataFactory.CreateIndexerParameterDataProvider(int startOffset, IType type, AstNode resolvedNode)
{ {
throw new NotImplementedException(); return CreateMethodDataProvider(startOffset, type.GetProperties(p => p.IsIndexer));
} }
IParameterDataProvider IParameterCompletionDataFactory.CreateTypeParameterDataProvider(int startOffset, IEnumerable<IType> types) IParameterDataProvider IParameterCompletionDataFactory.CreateTypeParameterDataProvider(int startOffset, IEnumerable<IType> types)
{ {
throw new NotImplementedException(); return null;
} }
#endregion #endregion
} }

108
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpInsightItem.cs

@ -2,11 +2,14 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Generic; using System.IO;
using System.Linq; using System.Text;
using ICSharpCode.NRefactory.Completion; using System.Windows;
using System.Windows.Controls;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
namespace CSharpBinding.Completion namespace CSharpBinding.Completion
@ -14,73 +17,84 @@ namespace CSharpBinding.Completion
sealed class CSharpInsightItem : IInsightItem sealed class CSharpInsightItem : IInsightItem
{ {
public readonly IParameterizedMember Method; public readonly IParameterizedMember Method;
readonly IAmbience ambience;
public CSharpInsightItem(IParameterizedMember method, IAmbience ambience) public CSharpInsightItem(IParameterizedMember method)
{ {
this.Method = method; this.Method = method;
this.ambience = ambience;
} }
string header; TextBlock header;
public object Header { public object Header {
get { get {
if (header == null) { if (header == null) {
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags; header = new TextBlock();
header = ambience.ConvertEntity(Method); GenerateHeader();
} }
return header; return header;
} }
} }
public object Content { int highlightedParameterIndex = -1;
get { return null; }
}
}
sealed class CSharpParameterDataProvider : IParameterDataProvider
{
readonly int startOffset;
internal readonly IReadOnlyList<CSharpInsightItem> items;
public CSharpParameterDataProvider(int startOffset, IEnumerable<CSharpInsightItem> items)
{
this.startOffset = startOffset;
this.items = items.ToList();
}
int IParameterDataProvider.Count {
get { return items.Count; }
}
public int StartOffset {
get { return startOffset; }
}
string IParameterDataProvider.GetHeading(int overload, string[] parameterDescription, int currentParameter)
{
throw new NotImplementedException();
}
string IParameterDataProvider.GetDescription(int overload, int currentParameter) public void HighlightParameter(int parameterIndex)
{ {
throw new NotImplementedException(); if (highlightedParameterIndex == parameterIndex)
return;
this.highlightedParameterIndex = parameterIndex;
if (header != null)
GenerateHeader();
} }
string IParameterDataProvider.GetParameterDescription(int overload, int paramIndex) void GenerateHeader()
{ {
throw new NotImplementedException(); CSharpAmbience ambience = new CSharpAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
var stringBuilder = new StringBuilder();
var formatter = new ParameterHighlightingOutputFormatter(stringBuilder, highlightedParameterIndex);
ambience.ConvertEntity(Method, formatter, FormattingOptionsFactory.CreateSharpDevelop());
var inlineBuilder = new HighlightedInlineBuilder(stringBuilder.ToString());
inlineBuilder.SetFontWeight(formatter.parameterStartOffset, formatter.parameterLength, FontWeights.Bold);
header.Inlines.Clear();
header.Inlines.AddRange(inlineBuilder.CreateRuns());
} }
int IParameterDataProvider.GetParameterCount(int overload) public object Content {
{ get { return null; }
throw new NotImplementedException();
} }
bool IParameterDataProvider.AllowParameterList(int overload) sealed class ParameterHighlightingOutputFormatter : TextWriterOutputFormatter
{ {
throw new NotImplementedException(); StringBuilder b;
int highlightedParameterIndex;
int parameterIndex;
internal int parameterStartOffset;
internal int parameterLength;
public ParameterHighlightingOutputFormatter(StringBuilder b, int highlightedParameterIndex)
: base(new StringWriter(b))
{
this.b = b;
this.highlightedParameterIndex = highlightedParameterIndex;
}
public override void StartNode(AstNode node)
{
if (parameterIndex == highlightedParameterIndex && node is ParameterDeclaration) {
parameterStartOffset = b.Length;
}
base.StartNode(node);
}
public override void EndNode(AstNode node)
{
base.EndNode(node);
if (node is ParameterDeclaration) {
if (parameterIndex == highlightedParameterIndex)
parameterLength = b.Length - parameterStartOffset;
parameterIndex++;
}
}
} }
} }
} }

110
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpMethodInsight.cs

@ -0,0 +1,110 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
namespace CSharpBinding.Completion
{
sealed class CSharpMethodInsight : IParameterDataProvider
{
readonly int startOffset;
internal readonly IReadOnlyList<CSharpInsightItem> items;
readonly CSharpCompletionBinding binding;
readonly ITextEditor editor;
IInsightWindow window;
public CSharpMethodInsight(CSharpCompletionBinding binding, ITextEditor editor, int startOffset, IEnumerable<CSharpInsightItem> items)
{
Debug.Assert(binding != null);
Debug.Assert(editor != null);
Debug.Assert(items != null);
this.binding = binding;
this.editor = editor;
this.startOffset = startOffset;
this.items = items.ToList();
}
public void Show()
{
window = editor.ShowInsightWindow(items);
window.StartOffset = startOffset;
// closing the window at the end of the parameter list is handled by the CaretPositionChanged event
window.EndOffset = editor.Document.TextLength;
window.CaretPositionChanged += window_CaretPositionChanged;
}
void window_CaretPositionChanged(object sender, EventArgs e)
{
var completionContext = CSharpCompletionContext.Get(editor);
if (completionContext == null) {
window.Close();
return;
}
var completionFactory = new CSharpCompletionDataFactory(binding, editor, completionContext.TypeResolveContextAtCaret);
var pce = new CSharpParameterCompletionEngine(
editor.Document,
completionContext.CompletionContextProvider,
completionFactory,
completionContext.ProjectContent,
completionContext.TypeResolveContextAtCaret
);
UpdateHighlightedParameter(pce);
}
public void UpdateHighlightedParameter(CSharpParameterCompletionEngine pce)
{
int parameterIndex = pce.GetCurrentParameterIndex(window != null ? window.StartOffset : startOffset, editor.Caret.Offset);
if (parameterIndex < 0 && window != null) {
window.Close();
} else {
if (parameterIndex > 0)
parameterIndex--; // NR returns 1-based parameter index
foreach (var item in items)
item.HighlightParameter(parameterIndex);
}
}
#region IParameterDataProvider implementation
int IParameterDataProvider.Count {
get { return items.Count; }
}
int IParameterDataProvider.StartOffset {
get { return startOffset; }
}
string IParameterDataProvider.GetHeading(int overload, string[] parameterDescription, int currentParameter)
{
throw new NotImplementedException();
}
string IParameterDataProvider.GetDescription(int overload, int currentParameter)
{
throw new NotImplementedException();
}
string IParameterDataProvider.GetParameterDescription(int overload, int paramIndex)
{
throw new NotImplementedException();
}
int IParameterDataProvider.GetParameterCount(int overload)
{
throw new NotImplementedException();
}
bool IParameterDataProvider.AllowParameterList(int overload)
{
throw new NotImplementedException();
}
#endregion
}
}

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -106,7 +106,6 @@
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
</Compile> </Compile>
<Compile Include="Src\Editor\CodeCompletion\ICompletionItemHandler.cs" /> <Compile Include="Src\Editor\CodeCompletion\ICompletionItemHandler.cs" />
<Compile Include="Src\Editor\CodeCompletion\IInsightWindowHandler.cs" />
<Compile Include="Src\Editor\CodeCompletion\NRefactoryInsightWindowHandler.cs" /> <Compile Include="Src\Editor\CodeCompletion\NRefactoryInsightWindowHandler.cs" />
<Compile Include="Src\Editor\Commands\ClassBookmarkSubmenuBuilder.cs" /> <Compile Include="Src\Editor\Commands\ClassBookmarkSubmenuBuilder.cs" />
<Compile Include="Src\Editor\Commands\ClassMemberMenuBuilder.cs" /> <Compile Include="Src\Editor\Commands\ClassMemberMenuBuilder.cs" />

14
src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindowHandler.cs

@ -1,14 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion
{
public interface IInsightWindowHandler
{
void InitializeOpenedInsightWindow(ITextEditor editor, IInsightWindow insightWindow);
bool InsightRefreshOnComma(ITextEditor editor, char ch, out IInsightWindow insightWindow);
void HighlightParameter(IInsightWindow window, int index);
}
}
Loading…
Cancel
Save