提交 c3b3e1f3 编写于 作者: I Ivan Basov

intellisense for the type name started working

上级 566ad914
......@@ -20,12 +20,12 @@ public TestChangeSignatureOptionsService()
{
}
AddedParameterResult IChangeSignatureOptionsService.GetAddedParameter(Document document, TextSpan insertionSpan)
AddedParameterResult IChangeSignatureOptionsService.GetAddedParameter(Document document, int insertPosition)
{
throw new System.NotImplementedException();
}
ChangeSignatureOptionsResult IChangeSignatureOptionsService.GetChangeSignatureOptions(ISymbol symbol, TextSpan insertionSpan, ParameterConfiguration parameters, Document document, INotificationService notificationService)
ChangeSignatureOptionsResult IChangeSignatureOptionsService.GetChangeSignatureOptions(ISymbol symbol, int insertPosition, ParameterConfiguration parameters, Document document, INotificationService notificationService)
{
var list = parameters.ToListOfParameters();
......
......@@ -146,11 +146,29 @@ private static int TryGetSelectedIndexFromDeclaration(int position, SyntaxNode m
return parameters != null ? GetParameterIndex(parameters.Parameters, position) : 0;
}
// TODO this is a rough algorithm: find the first ( and add 1.
// Find the position to insert the new parameter.
// We will insert a new comma and a parameter.
private static int TryGetInsertPositionFromDeclaration(SyntaxNode matchingNode)
{
var parameters = matchingNode.ChildNodes().OfType<ParameterListSyntax>().SingleOrDefault();
return parameters != null ? parameters.OpenParenToken.SpanStart + 1 : 0;
// TODO should we error process this?
if (parameters == null) { return 0; }
if (parameters.Parameters.Count > 0 &&
parameters.Parameters.Last().Modifiers.Any(SyntaxKind.ParamsKeyword))
{
// (a, b, c, d put here ->, params e)
// (a, b, c, d,<- new comma <new parameter> ->, params e)
return parameters.Parameters.GetSeparators().Last().SpanStart;
}
// ( put here->)
// (,<- new comma for intellisense <new parameter>)
//
// (a, b, c, d put here->)
// (a, b, c, d,<- new comma <new parameter>)
return parameters.CloseParenToken.SpanStart;
}
private SyntaxNode GetMatchingNode(SyntaxNode node, bool restrictToDeclarations)
......
......@@ -143,7 +143,7 @@ internal ChangeSignatureResult ChangeSignature(Document document, int position,
}
return new ChangeSignatureAnalyzedContext(
document, symbol, parameterConfiguration, new TextSpan(insertPosition, 0));
document, symbol, parameterConfiguration, insertPosition);
}
private async Task<ChangeSignatureResult> ChangeSignatureWithContextAsync(ChangeSignatureAnalyzedContext context, CancellationToken cancellationToken)
......@@ -173,7 +173,7 @@ internal ChangeSignatureOptionsResult GetChangeSignatureOptions(ChangeSignatureA
return changeSignatureOptionsService.GetChangeSignatureOptions(
context.Symbol,
context.InsertionSpan,
context.InsertPosition,
context.ParameterConfiguration,
context.Document,
notificationService);
......
......@@ -12,19 +12,19 @@ internal sealed class ChangeSignatureAnalyzedContext
public readonly ISymbol Symbol;
public readonly CannotChangeSignatureReason CannotChangeSignatureReason;
public readonly ParameterConfiguration ParameterConfiguration;
public readonly TextSpan InsertionSpan;
public readonly int InsertPosition;
public Solution Solution => Project.Solution;
public ChangeSignatureAnalyzedContext(
Document document, ISymbol symbol, ParameterConfiguration parameterConfiguration, TextSpan insertionSpan)
Document document, ISymbol symbol, ParameterConfiguration parameterConfiguration, int insertPosition)
{
CanChangeSignature = true;
Document = document;
Project = document.Project;
Symbol = symbol;
ParameterConfiguration = parameterConfiguration;
InsertionSpan = insertionSpan;
InsertPosition = insertPosition;
CannotChangeSignatureReason = CannotChangeSignatureReason.None;
}
......
......@@ -10,11 +10,11 @@ internal interface IChangeSignatureOptionsService : IWorkspaceService
{
ChangeSignatureOptionsResult GetChangeSignatureOptions(
ISymbol symbol,
TextSpan insertionSpan,
int insertPosition,
ParameterConfiguration parameters,
Document document,
INotificationService notificationService);
AddedParameterResult GetAddedParameter(Document document, TextSpan insertionSpan);
AddedParameterResult GetAddedParameter(Document document, int insertPosition);
}
}
......@@ -13,8 +13,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ChangeSignature
/// </summary>
internal partial class AddParameterDialog : DialogWindow
{
private readonly AddParameterDialogViewModel _viewModel;
private readonly IVsTextBuffer _textBuffer;
public readonly AddParameterDialogViewModel ViewModel;
private readonly IVsTextLines _vsTextLines;
private readonly IVsTextView _textView;
private readonly IWpfTextView _wpfTextView;
......@@ -30,13 +30,12 @@ internal partial class AddParameterDialog : DialogWindow
public string AddParameterDialogTitle { get { return ServicesVSResources.Add_Parameter; } }
public AddParameterDialog(
AddParameterDialogViewModel viewModel,
IVsTextBuffer textBuffer,
IVsTextLines vsTextLines,
IVsTextView vsTextView,
IWpfTextView wpfTextView)
{
_viewModel = viewModel;
_textBuffer = textBuffer;
ViewModel = new AddParameterDialogViewModel();
_vsTextLines = vsTextLines;
_textView = vsTextView;
_wpfTextView = wpfTextView;
this.Loaded += AddParameterDialog_Loaded;
......@@ -47,14 +46,16 @@ internal partial class AddParameterDialog : DialogWindow
private void AddParameterDialog_Loaded(object sender, RoutedEventArgs e)
{
IntellisenseTextBox typeNameTextBox = new IntellisenseTextBox(
_textBuffer as IVsTextLines, _textView, _wpfTextView, TypeNameContentControl);
_vsTextLines, _textView, _wpfTextView, TypeNameContentControl);
this.TypeNameContentControl.Content = typeNameTextBox;
}
private void OK_Click(object sender, RoutedEventArgs e)
{
if (_viewModel.TrySubmit())
if (ViewModel.TrySubmit())
{
// TODO maybe we should try binding.
ViewModel.TypeName = ((IntellisenseTextBox)TypeNameContentControl.Content).Text;
DialogResult = true;
}
}
......
......@@ -19,10 +19,19 @@ internal class AddParameterTextViewModelProvider : ITextViewModelProvider
public ITextViewModel CreateTextViewModel(ITextDataModel dataModel, ITextViewRoleSet roles)
{
var projectionSnapshot = (IProjectionSnapshot)dataModel.DataBuffer.CurrentSnapshot;
// There are three spans:
// 1. From the start of the document and to the inserted comma before the insertion.
// 2. The insertion span - we need to catch it here.
// 3. The rest of the document.
var span = projectionSnapshot.GetSourceSpans()[1];
var mappedSpans = projectionSnapshot.MapFromSourceSnapshot(span);
var elisionBuffer =
ProjectionBufferFactoryService.CreateElisionBuffer(/*resolver=*/null,
new NormalizedSnapshotSpanCollection(new SnapshotSpan(dataModel.DataBuffer.CurrentSnapshot, 85, 0)),
ElisionBufferOptions.None); //dataModel.DataBuffer.ContentType);
new NormalizedSnapshotSpanCollection(
new[]{ new SnapshotSpan(dataModel.DocumentBuffer.CurrentSnapshot, mappedSpans[0])
}),
ElisionBufferOptions.None);
return new ElisionBufferTextViewModel(dataModel, elisionBuffer);
}
......
......@@ -132,7 +132,7 @@ private void Restore_Click(object sender, RoutedEventArgs e)
private void Add_Click(object sender, RoutedEventArgs e)
{
var changeSignatureOptionsService = _viewModel.Document.Project.Solution.Workspace.Services.GetService<IChangeSignatureOptionsService>();
var result = changeSignatureOptionsService.GetAddedParameter(_viewModel.Document, _viewModel.InsertionSpan);
var result = changeSignatureOptionsService.GetAddedParameter(_viewModel.Document, _viewModel.InsertPosition);
if (!result.IsCancelled)
{
......
......@@ -31,7 +31,7 @@ internal class ChangeSignatureDialogViewModel : AbstractNotifyPropertyChanged
private readonly List<ParameterViewModel> _parameterGroup2;
private readonly ParameterViewModel _paramsParameter;
private HashSet<ParameterViewModel> _disabledParameters = new HashSet<ParameterViewModel>();
public readonly TextSpan InsertionSpan;
public readonly int InsertPosition;
private ImmutableArray<SymbolDisplayPart> _declarationParts;
private bool _previewChanges;
......@@ -43,14 +43,14 @@ internal class ChangeSignatureDialogViewModel : AbstractNotifyPropertyChanged
ParameterConfiguration parameters,
ISymbol symbol,
Document document,
TextSpan insertionSpan,
int insertPosition,
IClassificationFormatMap classificationFormatMap,
ClassificationTypeMap classificationTypeMap)
{
_originalParameterConfiguration = parameters;
_notificationService = notificationService;
Document = document;
InsertionSpan = insertionSpan;
InsertPosition = insertPosition;
_classificationFormatMap = classificationFormatMap;
_classificationTypeMap = classificationTypeMap;
......@@ -177,7 +177,15 @@ public bool CanEdit
internal void Remove()
{
AllParameters[_selectedIndex.Value].IsRemoved = true;
if (AllParameters[_selectedIndex.Value] is AddedParameterViewModel)
{
AllParameters.Remove(AllParameters[_selectedIndex.Value]);
}
else
{
AllParameters[_selectedIndex.Value].IsRemoved = true;
}
RemoveRestoreNotifyPropertyChanged();
}
......
......@@ -20,7 +20,6 @@
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using ImportingConstructorAttribute = System.Composition.ImportingConstructorAttribute;
using TextSpan = Microsoft.CodeAnalysis.Text.TextSpan;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ChangeSignature
{
......@@ -59,7 +58,7 @@ internal class VisualStudioChangeSignatureOptionsService : IChangeSignatureOptio
public ChangeSignatureOptionsResult GetChangeSignatureOptions(
ISymbol symbol,
TextSpan insertionSpan,
int insertPosition,
ParameterConfiguration parameters,
Document document,
INotificationService notificationService)
......@@ -69,7 +68,7 @@ internal class VisualStudioChangeSignatureOptionsService : IChangeSignatureOptio
parameters,
symbol,
document,
insertionSpan,
insertPosition,
_classificationFormatMap,
_classificationTypeMap);
......@@ -84,13 +83,14 @@ internal class VisualStudioChangeSignatureOptionsService : IChangeSignatureOptio
return new ChangeSignatureOptionsResult { IsCancelled = true };
}
public AddedParameterResult GetAddedParameter(Document document, TextSpan insertionSpan)
public AddedParameterResult GetAddedParameter(Document document, int insertPosition)
{
var (dialog, viewModel) = CreateAddParameterDialogAsync(document, insertionSpan, CancellationToken.None).Result;
var dialog = CreateAddParameterDialogAsync(document, insertPosition, CancellationToken.None).Result;
var result = dialog.ShowModal();
if (result.HasValue && result.Value)
{
AddParameterDialogViewModel viewModel = dialog.ViewModel;
return new AddedParameterResult
{
IsCancelled = false,
......@@ -106,46 +106,24 @@ public AddedParameterResult GetAddedParameter(Document document, TextSpan insert
}
}
private async Task<(AddParameterDialog, AddParameterDialogViewModel)> CreateAddParameterDialogAsync(
Document document, TextSpan insertionSpan, CancellationToken cancellationToken)
private async Task<AddParameterDialog> CreateAddParameterDialogAsync(
Document document, int insertPosition, CancellationToken cancellationToken)
{
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var sourceText = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);
var documentText = sourceText.ToString();
var roleSet = _textEditorFactoryService.CreateTextViewRoleSet(
PredefinedTextViewRoles.Editable,
PredefinedTextViewRoles.Interactive,
AddParameterTextViewRole);
var vsTextBuffer = _editorAdaptersFactoryService.CreateVsTextBufferAdapter(_serviceProvider, _contentType);
vsTextBuffer.InitializeContent(documentText, documentText.Length);
var vsTextView = _editorAdaptersFactoryService.CreateVsTextViewAdapter(_serviceProvider, roleSet);
var initView = new[] {
new INITVIEW()
{
fSelectionMargin = 0,
fWidgetMargin = 0,
fDragDropMove = 0,
IndentStyle = vsIndentStyle.vsIndentStyleNone
}
};
vsTextView.Initialize(
vsTextBuffer as IVsTextLines,
IntPtr.Zero,
(uint)TextViewInitFlags3.VIF_NO_HWND_SUPPORT,
initView);
IVsTextLines vsTextLines = _editorAdaptersFactoryService.CreateVsTextBufferAdapter(_serviceProvider, _contentType) as IVsTextLines;
vsTextLines.InitializeContent(documentText.Insert(insertPosition, ","), documentText.Length);
var originalContextBuffer = _editorAdaptersFactoryService.GetDataBuffer(vsTextBuffer);
var originalContextBuffer = _editorAdaptersFactoryService.GetDataBuffer(vsTextLines);
// Get the workspace, and from there, the solution and document containing this buffer.
// If there's an ExternalSource, we won't get a document. Give up in that case.
var solution = document.Project.Solution;
// Wrap the original ContextBuffer in a projection buffer that we can make read-only
var contextBuffer = _projectionBufferFactoryService.CreateProjectionBuffer(null,
new object[] { CreateFullTrackingSpan(originalContextBuffer.CurrentSnapshot, SpanTrackingMode.EdgeInclusive) }, ProjectionBufferOptions.None, _contentType);
new object[] { originalContextBuffer.CurrentSnapshot.CreateFullTrackingSpan(SpanTrackingMode.EdgeInclusive) }, ProjectionBufferOptions.None, _contentType);
// Make projection readonly so we can't edit it by mistake.
using (var regionEdit = contextBuffer.CreateReadOnlyRegionEdit())
......@@ -157,22 +135,21 @@ public AddedParameterResult GetAddedParameter(Document document, TextSpan insert
// Adjust the context point to ensure that the right information is in scope.
// For example, we may need to move the point to the end of the last statement in a method body
// in order to be able to access all local variables.
var contextPoint = insertionSpan.Start;
//var adjustedContextPoint = GetAdjustedContextPoint(contextPoint, document);
var adjustedContextPoint = contextPoint;
// + 1 to support inserted comma
var contextPoint = insertPosition + 1;
// Get the previous span/text. We might have to insert another newline or something.
var previousStatementSpan = CreateTrackingSpanFromStartToIndex(contextBuffer.CurrentSnapshot, adjustedContextPoint, SpanTrackingMode.EdgeNegative);
var previousStatementSpan = contextBuffer.CurrentSnapshot.CreateTrackingSpanFromStartToIndex(contextPoint, SpanTrackingMode.EdgeNegative);
// Get the appropriate ITrackingSpan for the window the user is typing in
var mappedSpan = contextBuffer.CurrentSnapshot.CreateTrackingSpan(adjustedContextPoint, 0, SpanTrackingMode.EdgeExclusive);
var mappedSpan = contextBuffer.CurrentSnapshot.CreateTrackingSpan(contextPoint, 0, SpanTrackingMode.EdgeExclusive);
// Build the tracking span that includes the rest of the file
var restOfFileSpan = CreateTrackingSpanFromIndexToEnd(contextBuffer.CurrentSnapshot, adjustedContextPoint, SpanTrackingMode.EdgePositive);
var restOfFileSpan = contextBuffer.CurrentSnapshot.CreateTrackingSpanFromIndexToEnd(contextPoint, SpanTrackingMode.EdgePositive);
// Put it all into a projection buffer
var projectionBuffer = _projectionBufferFactoryService.CreateProjectionBuffer(null,
new object[] { previousStatementSpan, mappedSpan, ";", restOfFileSpan }, ProjectionBufferOptions.None, _contentType);
new object[] { previousStatementSpan, mappedSpan, restOfFileSpan }, ProjectionBufferOptions.None, _contentType);
// Fork the solution using this new primary buffer for the document and all of its linked documents.
var forkedSolution = solution.WithDocumentText(document.Id, projectionBuffer.CurrentSnapshot.AsText(), PreservationMode.PreserveIdentity);
......@@ -187,39 +164,41 @@ public AddedParameterResult GetAddedParameter(Document document, TextSpan insert
workspace.OpenDocument(workspace.ChangeSignatureDocumentId, originalContextBuffer.AsTextContainer());
foreach (var link in document.GetLinkedDocumentIds())
{
workspace.OpenDocument(link, projectionBuffer.AsTextContainer());
workspace.OpenDocument(link, originalContextBuffer.AsTextContainer());
}
// Start getting the compilation so the PartialSolution will be ready when the user starts typing in the window
await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
// TODO here we should hook the projection buffer.
var wpfTextView = _editorAdaptersFactoryService.GetWpfTextView(vsTextView);
wpfTextView.TextBuffer.ChangeContentType(_contentType, null);
var roleSet = _textEditorFactoryService.CreateTextViewRoleSet(
PredefinedTextViewRoles.Editable,
PredefinedTextViewRoles.Interactive,
AddParameterTextViewRole);
var viewModel = new AddParameterDialogViewModel();
var dialog = new AddParameterDialog(
viewModel,
vsTextBuffer,
vsTextView,
wpfTextView);
var vsTextView = _editorAdaptersFactoryService.CreateVsTextViewAdapter(_serviceProvider, roleSet);
return (dialog, viewModel);
}
var initView = new[] {
new INITVIEW()
{
fSelectionMargin = 0,
fWidgetMargin = 0,
fDragDropMove = 0,
IndentStyle = vsIndentStyle.vsIndentStyleNone
}
};
public static ITrackingSpan CreateFullTrackingSpan(ITextSnapshot textSnapshot, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(0, textSnapshot.Length), trackingMode);
}
_editorAdaptersFactoryService.SetDataBuffer(vsTextLines, projectionBuffer);
public static ITrackingSpan CreateTrackingSpanFromIndexToEnd(ITextSnapshot textSnapshot, int index, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(index, textSnapshot.Length), trackingMode);
}
vsTextView.Initialize(
vsTextLines,
IntPtr.Zero,
(uint)TextViewInitFlags3.VIF_NO_HWND_SUPPORT,
initView);
public static ITrackingSpan CreateTrackingSpanFromStartToIndex(ITextSnapshot textSnapshot, int index, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(0, index), trackingMode);
IWpfTextView wpfTextView = _editorAdaptersFactoryService.GetWpfTextView(vsTextView);
wpfTextView.TextBuffer.ChangeContentType(_contentType, null);
return new AddParameterDialog(vsTextLines, vsTextView, wpfTextView);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.VisualStudio.Text;
namespace Microsoft.VisualStudio.LanguageServices.Implementation
{
internal static class ITextSnapshotExtensions
{
public static ITrackingSpan CreateFullTrackingSpan(this ITextSnapshot textSnapshot, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(0, textSnapshot.Length), trackingMode);
}
public static ITrackingSpan CreateTrackingSpanFromIndexToEnd(this ITextSnapshot textSnapshot, int index, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(index, textSnapshot.Length), trackingMode);
}
public static ITrackingSpan CreateTrackingSpanFromStartToIndex(this ITextSnapshot textSnapshot, int index, SpanTrackingMode trackingMode)
{
return textSnapshot.CreateTrackingSpan(Span.FromBounds(0, index), trackingMode);
}
}
}
......@@ -95,6 +95,7 @@ public string Text
{
int length;
string text;
// TODO why 0?
this._vsTextLines.GetLengthOfLine(0, out length);
this._vsTextLines.GetLineText(0, 0, 0, length, out text);
return text;
......@@ -487,8 +488,8 @@ public bool HandleKeyDown()
/// and posts it to the internal editor control.</remarks>
public bool HandleKeyDown(OLE.Interop.MSG message)
{
uint editCmdID = 0;
Guid editCmdGuid = Guid.Empty;
uint editCmdID;
Guid editCmdGuid;
int VariantSize = 16;
IVsFilterKeys2 filterKeys = Package.GetGlobalService(typeof(SVsFilterKeys)) as IVsFilterKeys2;
......
......@@ -441,7 +441,7 @@ class MyClass
ParameterConfiguration.Create(symbol.GetParameters().Select(Function(p) DirectCast(New ExistingParameter(p), Parameter)).ToList(), symbol.IsExtensionMethod(), selectedIndex:=0),
symbol,
workspaceDoc,
insertionSpan:=New Microsoft.CodeAnalysis.Text.TextSpan(0, 0),
insertPosition:=0,
workspace.ExportProvider.GetExportedValue(Of IClassificationFormatMapService)().GetClassificationFormatMap("text"),
workspace.ExportProvider.GetExportedValue(Of ClassificationTypeMap)())
Return New ChangeSignatureViewModelTestState(viewModel, symbol.GetParameters())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册