protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            ObjectCreationExpressionSyntax objectCreationExpression;
            if (!TryGetObjectCreationExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out objectCreationExpression))
            {
                return null;
            }

            var semanticModel = await document.GetSemanticModelForNodeAsync(objectCreationExpression, cancellationToken).ConfigureAwait(false);
            var type = semanticModel.GetTypeInfo(objectCreationExpression, cancellationToken).Type as INamedTypeSymbol;
            if (type == null)
            {
                return null;
            }

            var within = semanticModel.GetEnclosingNamedType(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(objectCreationExpression.ArgumentList);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            return CreateSignatureHelpItems(type.TypeKind == TypeKind.Delegate
                ? GetDelegateTypeConstructors(objectCreationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, type, within, cancellationToken)
                : GetNormalTypeConstructors(document, objectCreationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, type, within, cancellationToken),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            InvocationExpressionSyntax invocationExpression;
            if (!TryGetInvocationExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out invocationExpression))
            {
                return null;
            }

            var semanticModel = await document.GetSemanticModelForNodeAsync(invocationExpression, cancellationToken).ConfigureAwait(false);
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            // get the regular signature help items
            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            var methodGroup = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken)
                                           .OfType<IMethodSymbol>()
                                           .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation);

            // try to bind to the actual method
            var symbolInfo = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken);
            var matchedMethodSymbol = symbolInfo.Symbol as IMethodSymbol;

            // if the symbol could be bound, replace that item in the symbol list
            if (matchedMethodSymbol != null && matchedMethodSymbol.IsGenericMethod)
            {
                methodGroup = methodGroup.Select(m => matchedMethodSymbol.OriginalDefinition == m ? matchedMethodSymbol : m);
            }

            methodGroup = methodGroup.Sort(symbolDisplayService, semanticModel, invocationExpression.SpanStart);

            var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol;

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();

            var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            if (methodGroup.Any())
            {
                return CreateSignatureHelpItems(
                    GetMethodGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, cancellationToken),
                    textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
            }
            else if (expressionType != null && expressionType.TypeKind == TypeKind.Delegate)
            {
                return CreateSignatureHelpItems(
                    GetDelegateInvokeItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, expressionType, cancellationToken),
                    textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
            }
            else
            {
                return null;
            }
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ConstructorInitializerSyntax constructorInitializer;
            if (!TryGetConstructorInitializer(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out constructorInitializer))
            {
                return null;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var within = semanticModel.GetEnclosingNamedType(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            if (within.TypeKind != TypeKind.Struct && within.TypeKind != TypeKind.Class)
            {
                return null;
            }

            var type = constructorInitializer.Kind() == SyntaxKind.BaseConstructorInitializer
                ? within.BaseType
                : within;

            if (type == null)
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            var accessibleConstructors = type.InstanceConstructors
                                             .Where(c => c.IsAccessibleWithin(within))
                                             .Where(c => c.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation))
                                             .Sort(symbolDisplayService, semanticModel, constructorInitializer.SpanStart);

            if (!accessibleConstructors.Any())
            {
                return null;
            }

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(constructorInitializer.ArgumentList);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            return CreateSignatureHelpItems(accessibleConstructors.Select(c =>
                Convert(c, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
            public void ComputeModel(
                IList<ISignatureHelpProvider> matchedProviders,
                IList<ISignatureHelpProvider> unmatchedProviders,
                SignatureHelpTriggerInfo triggerInfo)
            {
                AssertIsForeground();

                var caretPosition = Controller.TextView.GetCaretPoint(Controller.SubjectBuffer).Value;
                var disconnectedBufferGraph = new DisconnectedBufferGraph(Controller.SubjectBuffer, Controller.TextView.TextBuffer);

                // If we've already computed a model, then just use that.  Otherwise, actually
                // compute a new model and send that along.
                Computation.ChainTaskAndNotifyControllerWhenFinished(
                    (model, cancellationToken) => ComputeModelInBackgroundAsync(model, matchedProviders, unmatchedProviders, caretPosition, disconnectedBufferGraph, triggerInfo, cancellationToken));
            }
        public async Task <SignatureHelpItems> GetSignatureHelp(SignatureHelpTriggerInfo trigger, int position)
        {
            var document = GetCurrentDocument();

            foreach (var provider in _signatureHelpProviders)
            {
                var items = await provider.GetItemsAsync(document, position, trigger, CancellationToken.None)
                            .ConfigureAwait(false);

                if (items != null)
                {
                    return(items);
                }
            }
            return(null);
        }
Exemple #6
0
            public void ComputeModel(
                ImmutableArray <ISignatureHelpProvider> providers,
                SignatureHelpTriggerInfo triggerInfo)
            {
                AssertIsForeground();

                var caretPosition           = Controller.TextView.GetCaretPoint(Controller.SubjectBuffer).Value;
                var disconnectedBufferGraph = new DisconnectedBufferGraph(Controller.SubjectBuffer, Controller.TextView.TextBuffer);

                // If we've already computed a model, then just use that.  Otherwise, actually
                // compute a new model and send that along.
                Computation.ChainTaskAndNotifyControllerWhenFinished(
                    (model, cancellationToken) => ComputeModelInBackgroundAsync(
                        model, providers, caretPosition, disconnectedBufferGraph,
                        triggerInfo, cancellationToken));
            }
        void Start(SignatureHelpInfo info, SnapshotPoint triggerPosition, SignatureHelpTriggerInfo triggerInfo)
        {
            CancelFetchItems();
            Debug.Assert(cancellationTokenSource == null);
            cancellationTokenSource = new CancellationTokenSource();
            var cancellationTokenSourceTmp = cancellationTokenSource;

            StartAsync(info, triggerPosition, triggerInfo, cancellationTokenSource.Token)
            .ContinueWith(t => {
                var ex = t.Exception;
                // Free resources
                if (cancellationTokenSource == cancellationTokenSourceTmp)
                {
                    CancelFetchItems();
                }
            }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }
        private async Task TestSignatureHelpWorkerSharedAsync(
            string code,
            int cursorPosition,
            SourceCodeKind sourceCodeKind,
            Document document,
            TextSpan?textSpan,
            IEnumerable <SignatureHelpTestItem> expectedOrderedItemsOrNull = null,
            bool usePreviousCharAsTrigger = false)
        {
            var signatureHelpProvider = CreateSignatureHelpProvider();
            var triggerInfo           = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);

            if (usePreviousCharAsTrigger)
            {
                triggerInfo = new SignatureHelpTriggerInfo(
                    SignatureHelpTriggerReason.TypeCharCommand,
                    code.ElementAt(cursorPosition - 1));

                if (!signatureHelpProvider.IsTriggerCharacter(triggerInfo.TriggerCharacter.Value))
                {
                    return;
                }
            }

            var items = await signatureHelpProvider.GetItemsAsync(document, cursorPosition, triggerInfo, CancellationToken.None);

            // If we're expecting 0 items, then there's no need to compare them
            if ((expectedOrderedItemsOrNull == null || !expectedOrderedItemsOrNull.Any()) && items == null)
            {
                return;
            }

            AssertEx.NotNull(items, "Signature help provider returned null for items. Did you forget $$ in the test or is the test otherwise malformed, e.g. quotes not escaped?");

            // Verify the span
            if (textSpan != null)
            {
                Assert.Equal(textSpan, items.ApplicableSpan);
            }

            if (expectedOrderedItemsOrNull != null)
            {
                CompareAndAssertCollectionsAndCurrentParameter(expectedOrderedItemsOrNull, items);
                CompareSelectedIndex(expectedOrderedItemsOrNull, items.SelectedItemIndex);
            }
        }
Exemple #9
0
            private static async Task <(ISignatureHelpProvider provider, SignatureHelpItems items)> ComputeItemsAsync(
                ImmutableArray <ISignatureHelpProvider> providers,
                SnapshotPoint caretPosition,
                SignatureHelpTriggerInfo triggerInfo,
                SignatureHelpOptions options,
                Document document,
                CancellationToken cancellationToken)
            {
                try
                {
                    ISignatureHelpProvider bestProvider = null;
                    SignatureHelpItems     bestItems    = null;

                    // TODO(cyrusn): We're calling into extensions, we need to make ourselves resilient
                    // to the extension crashing.
                    foreach (var provider in providers)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var currentItems = await provider.GetItemsAsync(document, caretPosition, triggerInfo, options, cancellationToken).ConfigureAwait(false);

                        if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(caretPosition.Position))
                        {
                            // If another provider provides sig help items, then only take them if they
                            // start after the last batch of items.  i.e. we want the set of items that
                            // conceptually are closer to where the caret position is.  This way if you have:
                            //
                            //  Goo(new Bar($$
                            //
                            // Then invoking sig help will only show the items for "new Bar(" and not also
                            // the items for "Goo(..."
                            if (IsBetter(bestItems, currentItems.ApplicableSpan))
                            {
                                bestItems    = currentItems;
                                bestProvider = provider;
                            }
                        }
                    }

                    return(bestProvider, bestItems);
                }
                catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical))
                {
                    return(null, null);
                }
            }
        async Task StartAsync(SignatureHelpInfo info, SnapshotPoint triggerPosition, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            // This helps a little to speed up the code
            ProfileOptimizationHelper.StartProfile("roslyn-sighelp-" + info.SignatureHelpService.Language);

            var result = await info.SignatureHelpService.GetItemsAsync(info.Document, triggerPosition.Position, triggerInfo, cancellationToken);

            if (result == null)
            {
                Dispose();
                return;
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }
            StartSession(triggerPosition, result);
        }
Exemple #11
0
        protected override async Task <SignatureHelpItems?> GetItemsWorkerAsync(
            Document document,
            int position,
            SignatureHelpTriggerInfo triggerInfo,
            CancellationToken cancellationToken
            )
        {
            var root = await document
                       .GetRequiredSyntaxRootAsync(cancellationToken)
                       .ConfigureAwait(false);

            var semanticModel = await document
                                .GetRequiredSemanticModelAsync(cancellationToken)
                                .ConfigureAwait(false);

            var syntaxFacts   = document.GetRequiredLanguageService <ISyntaxFactsService>();
            var typeInferrer  = document.GetRequiredLanguageService <ITypeInferenceService>();
            var inferredTypes = FindNearestTupleConstructionWithInferrableType(
                root,
                semanticModel,
                position,
                triggerInfo,
                typeInferrer,
                syntaxFacts,
                cancellationToken,
                out var targetExpression
                );

            if (inferredTypes == null || !inferredTypes.Any())
            {
                return(null);
            }

            return(CreateItems(
                       position,
                       root,
                       syntaxFacts,
                       targetExpression !,
                       semanticModel,
                       inferredTypes,
                       cancellationToken
                       ));
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            AttributeSyntax attribute;
            if (!TryGetAttributeExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out attribute))
            {
                return null;
            }

            var semanticModel = await document.GetSemanticModelForNodeAsync(attribute, cancellationToken).ConfigureAwait(false);
            var attributeType = semanticModel.GetTypeInfo(attribute, cancellationToken).Type as INamedTypeSymbol;
            if (attributeType == null)
            {
                return null;
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            var accessibleConstructors = attributeType.InstanceConstructors
                                                      .Where(c => c.IsAccessibleWithin(within))
                                                      .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                                                      .Sort(symbolDisplayService, semanticModel, attribute.SpanStart);

            if (!accessibleConstructors.Any())
            {
                return null;
            }

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormatter = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(attribute.ArgumentList);

            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
            return CreateSignatureHelpItems(accessibleConstructors.Select(c =>
                Convert(c, within, attribute, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormatter, cancellationToken)),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
        // TODO: Some of this is duplicated from Controller.Session_ComputeModel.cs
        private async Task <SignatureHelpItems> GetItemsAsync(LogicalDocument document, int position, CancellationToken cancellationToken)
        {
            var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);

            var providers = _signatureHelpProviders
                            .Where(x => x.Metadata.Language == document.Language)
                            .Select(x => x.Value);

            ISignatureHelpProvider bestProvider = null;
            SignatureHelpItems     bestItems    = null;

            foreach (var provider in providers)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var currentItems = await provider.GetItemsAsync(document, position, triggerInfo, cancellationToken);

                if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(position))
                {
                    // If another provider provides sig help items, then only take them if they
                    // start after the last batch of items.  i.e. we want the set of items that
                    // conceptually are closer to where the caret position is.  This way if you have:
                    //
                    //  Foo(new Bar($$
                    //
                    // Then invoking sig help will only show the items for "new Bar(" and not also
                    // the items for "Foo(..."
                    if (IsBetter(bestItems, currentItems.ApplicableSpan))
                    {
                        bestItems    = currentItems;
                        bestProvider = provider;
                    }
                }
            }

            return(bestItems);
        }
Exemple #14
0
 protected abstract Task <SignatureHelpItems?> GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken);
Exemple #15
0
        async Task InitializeAsync(ITextBuffer buffer, string code, MetadataReference[] refs, string languageName, ISynchronousTagger <IClassificationTag> tagger, CompilationOptions compilationOptions, ParseOptions parseOptions)
        {
            using (var workspace = new AdhocWorkspace(RoslynMefHostServices.DefaultServices)) {
                var documents = new List <DocumentInfo>();
                var projectId = ProjectId.CreateNewId();
                documents.Add(DocumentInfo.Create(DocumentId.CreateNewId(projectId), "main.cs", null, SourceCodeKind.Regular, TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())));

                var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "compilecodeproj", Guid.NewGuid().ToString(), languageName,
                                                     compilationOptions: compilationOptions
                                                     .WithOptimizationLevel(OptimizationLevel.Release)
                                                     .WithPlatform(Platform.AnyCpu)
                                                     .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default),
                                                     parseOptions: parseOptions,
                                                     documents: documents,
                                                     metadataReferences: refs,
                                                     isSubmission: false, hostObjectType: null);
                workspace.AddProject(projectInfo);
                foreach (var doc in documents)
                {
                    workspace.OpenDocument(doc.Id);
                }

                buffer.Replace(new Span(0, buffer.CurrentSnapshot.Length), code);

                {
                    // Initialize classification code paths
                    var spans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length));
                    foreach (var tagSpan in tagger.GetTags(spans, CancellationToken.None))
                    {
                    }
                }

                {
                    // Initialize completion code paths
                    var info = CompletionInfo.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        var completionTrigger = CompletionTrigger.Invoke;
                        var completionList    = await info.Value.CompletionService.GetCompletionsAsync(info.Value.Document, 0, completionTrigger);
                    }
                }

                {
                    // Initialize signature help code paths
                    var info = SignatureHelpInfo.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        int sigHelpIndex = code.IndexOf("sighelp");
                        Debug.Assert(sigHelpIndex >= 0);
                        var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);
                        var items       = await info.Value.SignatureHelpService.GetItemsAsync(info.Value.Document, sigHelpIndex, triggerInfo);
                    }
                }

                {
                    // Initialize quick info code paths
                    var info = QuickInfoState.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        int quickInfoIndex = code.IndexOf("Equals");
                        Debug.Assert(quickInfoIndex >= 0);
                        var item = await info.Value.QuickInfoService.GetItemAsync(info.Value.Document, quickInfoIndex);
                    }
                }
            }
        }
 protected abstract Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken);
Exemple #17
0
 Task <SignatureHelpItems?> ISignatureHelpProvider.GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, SignatureHelpOptions options, CancellationToken cancellationToken)
 => GetItemsAsync(document, position, triggerInfo, cancellationToken);
Exemple #18
0
        protected override async Task <SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            if (!TryGetElementAccessExpression(root, position, document.GetLanguageService <ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out var expression, out var openBrace))
            {
                return(null);
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var expressionSymbol = semanticModel.GetSymbolInfo(expression, cancellationToken).GetAnySymbol();

            // goo?[$$]
            if (expressionSymbol is INamedTypeSymbol namedType)
            {
                if (namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T &&
                    expression.IsKind(SyntaxKind.NullableType) &&
                    expression.IsChildNode <ArrayTypeSyntax>(a => a.ElementType))
                {
                    // Speculatively bind the type part of the nullable as an expression
                    var nullableTypeSyntax = (NullableTypeSyntax)expression;
                    var speculativeBinding = semanticModel.GetSpeculativeSymbolInfo(position, nullableTypeSyntax.ElementType, SpeculativeBindingOption.BindAsExpression);
                    expressionSymbol = speculativeBinding.GetAnySymbol();
                    expression       = nullableTypeSyntax.ElementType;
                }
            }

            if (expressionSymbol != null && expressionSymbol is INamedTypeSymbol)
            {
                return(null);
            }

            if (!TryGetIndexers(position, semanticModel, expression, cancellationToken, out var indexers, out var expressionType) &&
                !TryGetComIndexers(semanticModel, expression, cancellationToken, out indexers, out expressionType))
            {
                return(null);
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);

            if (within == null)
            {
                return(null);
            }

            var accessibleIndexers = indexers.WhereAsArray(
                m => m.IsAccessibleWithin(within, throughTypeOpt: expressionType));

            if (!accessibleIndexers.Any())
            {
                return(null);
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService <ISymbolDisplayService>();

            accessibleIndexers = accessibleIndexers.FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                                 .Sort(symbolDisplayService, semanticModel, expression.SpanStart);

            var anonymousTypeDisplayService           = document.Project.LanguageServices.GetService <IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService <IDocumentationCommentFormattingService>();
            var textSpan    = GetTextSpan(expression, openBrace);
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            return(CreateSignatureHelpItems(accessibleIndexers.Select(p =>
                                                                      Convert(p, openBrace, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)).ToList(),
                                            textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
        }
Exemple #19
0
        public async Task <SignatureHelpItems> GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            // This provider is exported for all workspaces - so limit it to just our workspace.
            if (document.Project.Solution.Workspace.Kind != WorkspaceKind.AnyCodeRoslynWorkspace)
            {
                return(null);
            }

            var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient;

            if (lspClient == null)
            {
                return(null);
            }

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var textDocumentPositionParams = ProtocolConversions.PositionToTextDocumentPositionParams(position, text, document);

            var signatureHelp = await lspClient.RequestAsync(Methods.TextDocumentSignatureHelp.ToLSRequest(), textDocumentPositionParams, cancellationToken).ConfigureAwait(false);

            if (signatureHelp == null || signatureHelp.Signatures == null || signatureHelp.Signatures.Length <= 0)
            {
                return(null);
            }

            var items = new List <SignatureHelpItem>();

            foreach (var signature in signatureHelp.Signatures)
            {
                items.Add(CreateSignatureHelpItem(signature));
            }

            var linePosition   = text.Lines.GetLinePosition(position);
            var applicableSpan = text.Lines.GetTextSpan(new CodeAnalysis.Text.LinePositionSpan(linePosition, linePosition));

            return(new SignatureHelpItems(items, applicableSpan, signatureHelp.ActiveParameter, signatureHelp.ActiveParameter, null, signatureHelp.ActiveSignature));
        }
Exemple #20
0
        public async Task <SignatureHelpItems> GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var mappedTriggerReason      = FSharpSignatureHelpTriggerReasonHelpers.ConvertFrom(triggerInfo.TriggerReason);
            var mappedTriggerInfo        = new FSharpSignatureHelpTriggerInfo(mappedTriggerReason, triggerInfo.TriggerCharacter);
            var mappedSignatureHelpItems = await _provider.GetItemsAsync(document, position, mappedTriggerInfo, cancellationToken).ConfigureAwait(false);

            if (mappedSignatureHelpItems != null)
            {
                return(new SignatureHelpItems(
                           mappedSignatureHelpItems.Items?.Select(x =>
                                                                  new SignatureHelpItem(
                                                                      x.IsVariadic,
                                                                      x.DocumentationFactory,
                                                                      x.PrefixDisplayParts,
                                                                      x.SeparatorDisplayParts,
                                                                      x.SuffixDisplayParts,
                                                                      x.Parameters.Select(y =>
                                                                                          new SignatureHelpParameter(
                                                                                              y.Name,
                                                                                              y.IsOptional,
                                                                                              y.DocumentationFactory,
                                                                                              y.DisplayParts,
                                                                                              y.PrefixDisplayParts,
                                                                                              y.SuffixDisplayParts,
                                                                                              y.SelectedDisplayParts)).ToList(),
                                                                      x.DescriptionParts)).ToList(),
                           mappedSignatureHelpItems.ApplicableSpan,
                           mappedSignatureHelpItems.ArgumentIndex,
                           mappedSignatureHelpItems.ArgumentCount,
                           mappedSignatureHelpItems.ArgumentName,
                           mappedSignatureHelpItems.SelectedItemIndex));
            }
            else
            {
                return(null);
            }
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax expression;
            SyntaxToken openBrace;
            if (!TryGetElementAccessExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out expression, out openBrace))
            {
                return null;
            }

            var semanticModel = await document.GetCSharpSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var expressionSymbol = semanticModel.GetSymbolInfo(expression, cancellationToken).GetAnySymbol();
            if (expressionSymbol is INamedTypeSymbol)
            {
                // foo?[$$]
                var namedType = (INamedTypeSymbol)expressionSymbol;
                if (namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T &&
                    expression.IsKind(SyntaxKind.NullableType) &&
                    expression.IsChildNode<ArrayTypeSyntax>(a => a.ElementType))
                {
                    // Speculatively bind the type part of the nullable as an expression
                    var nullableTypeSyntax = (NullableTypeSyntax)expression;
                    var speculativeBinding = semanticModel.GetSpeculativeSymbolInfo(position, nullableTypeSyntax.ElementType, SpeculativeBindingOption.BindAsExpression);
                    expressionSymbol = speculativeBinding.GetAnySymbol();
                    expression = nullableTypeSyntax.ElementType;
                }
            }

            if (expressionSymbol != null && expressionSymbol is INamedTypeSymbol)
            {
                return null;
            }

            IEnumerable<IPropertySymbol> indexers;
            ITypeSymbol expressionType;

            if (!TryGetIndexers(position, semanticModel, expression, cancellationToken, out indexers, out expressionType) &&
                !TryGetComIndexers(semanticModel, expression, cancellationToken, out indexers, out expressionType))
            {
                return null;
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            var accessibleIndexers = indexers.Where(m => m.IsAccessibleWithin(within, throughTypeOpt: expressionType));
            if (!accessibleIndexers.Any())
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            accessibleIndexers = accessibleIndexers.FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                                                   .Sort(symbolDisplayService, semanticModel, expression.SpanStart);

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = GetTextSpan(expression, openBrace);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            return CreateSignatureHelpItems(accessibleIndexers.Select(p =>
                Convert(p, openBrace, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
Exemple #22
0
        protected sealed override async Task <SignatureHelpItems> GetItemsWorkerAsync(LogicalDocument document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var sourceLocation = syntaxTree.MapRootFilePosition(position);
            var token          = ((SyntaxNode)syntaxTree.Root).FindTokenOnLeft(sourceLocation);

            var node = token.Parent
                       .AncestorsAndSelf()
                       .OfType <TNode>()
                       .FirstOrDefault(c => c.IsBetweenParentheses(sourceLocation));

            if (node == null)
            {
                return(null);
            }

            var rootSpan = node.GetTextSpanRoot();

            if (rootSpan == null)
            {
                return(null);
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (semanticModel == null)
            {
                return(null);
            }

            return(GetModel((SemanticModel)semanticModel, node, sourceLocation));
        }
        void IChainedCommandHandler <TypeCharCommandArgs> .ExecuteCommand(TypeCharCommandArgs args, Action nextHandler, CommandExecutionContext context)
        {
            AssertIsForeground();

            var allProviders = GetProviders();

            if (allProviders == null)
            {
                nextHandler();
                return;
            }

            // Note: while we're doing this, we don't want to hear about buffer changes (since we
            // know they're going to happen).  So we disconnect and reconnect to the event
            // afterwards.  That way we can hear about changes to the buffer that don't happen
            // through us.
            this.TextView.TextBuffer.PostChanged -= OnTextViewBufferPostChanged;
            try
            {
                nextHandler();
            }
            finally
            {
                this.TextView.TextBuffer.PostChanged += OnTextViewBufferPostChanged;
            }

            // We only want to process typechar if it is a normal typechar and no one else is
            // involved.  i.e. if there was a typechar, but someone processed it and moved the caret
            // somewhere else then we don't want signature help.  Also, if a character was typed but
            // something intercepted and placed different text into the editor, then we don't want
            // to proceed.
            //
            // Note: we do not want to pass along a text version here.  It is expected that multiple
            // version changes may happen when we call 'nextHandler' and we will still want to
            // proceed.  For example, if the user types "WriteL(", then that will involve two text
            // changes as completion commits that out to "WriteLine(".  But we still want to provide
            // sig help in this case.
            if (this.TextView.TypeCharWasHandledStrangely(this.SubjectBuffer, args.TypedChar))
            {
                // If we were computing anything, we stop.  We only want to process a typechar
                // if it was a normal character.
                DismissSessionIfActive();
                return;
            }

            // Separate the sig help providers into two buckets; one bucket for those that were triggered
            // by the typed character, and those that weren't.  To keep our queries to a minimum, we first
            // check with the textually triggered providers.  If none of those produced any sig help items
            // then we query the other providers to see if they can produce anything viable.  This takes
            // care of cases where the filtered set of providers didn't provide anything but one of the
            // other providers could still be valid, but doesn't explicitly treat the typed character as
            // a trigger character.
            var(textuallyTriggeredProviders, untriggeredProviders) = FilterProviders(allProviders, args.TypedChar);
            var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.TypeCharCommand, args.TypedChar);

            if (!IsSessionActive)
            {
                // No computation at all.  If this is not a trigger character, we just ignore it and
                // stay in this state.  Otherwise, if it's a trigger character, start up a new
                // computation and start computing the model in the background.
                if (textuallyTriggeredProviders.Any())
                {
                    // First create the session that represents that we now have a potential
                    // signature help list. Then tell it to start computing.
                    StartSession(textuallyTriggeredProviders, triggerInfo);
                    return;
                }
                else
                {
                    // No need to do anything.  Just stay in the state where we have no session.
                    return;
                }
            }
            else
            {
                var computed = false;
                if (allProviders.Any(p => p.IsRetriggerCharacter(args.TypedChar)))
                {
                    // The user typed a character that might close the scope of the current model.
                    // In this case, we should requery all providers.
                    //
                    // e.g.     Math.Max(Math.Min(1,2)$$
                    sessionOpt.ComputeModel(allProviders, new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.RetriggerCommand, triggerInfo.TriggerCharacter));
                    computed = true;
                }

                if (textuallyTriggeredProviders.Any())
                {
                    // The character typed was something like "(".  It can both filter a list if
                    // it was in a string like: Foo(bar, "(
                    //
                    // Or it can trigger a new list. Ask the computation to compute again.
                    sessionOpt.ComputeModel(
                        textuallyTriggeredProviders.Concat(untriggeredProviders), triggerInfo);
                    computed = true;
                }

                if (!computed)
                {
                    // A character was typed and we haven't updated our model; do so now.
                    sessionOpt.ComputeModel(allProviders, new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.RetriggerCommand));
                }
            }
        }
 private static bool IsNonTypeCharRetrigger(SignatureHelpTriggerInfo triggerInfo)
 => triggerInfo.TriggerReason == SignatureHelpTriggerReason.RetriggerCommand &&
 triggerInfo.TriggerCharacter == null;
Exemple #25
0
 public override System.Threading.Tasks.Task <CodeCompletion.ParameterHintingResult> HandleParameterCompletionAsync(CodeCompletion.CodeCompletionContext completionContext, SignatureHelpTriggerInfo triggerInfo, System.Threading.CancellationToken token)
 {
     return(completionTextEditorExtension.HandleParameterCompletionAsync(completionContext, triggerInfo, token));
 }
Exemple #26
0
 public void ComputeModel(
     IList <ISignatureHelpProvider> providers,
     SignatureHelpTriggerInfo triggerInfo)
 {
     ComputeModel(providers, SpecializedCollections.EmptyList <ISignatureHelpProvider>(), triggerInfo);
 }
 public void ComputeModel(
     IList<ISignatureHelpProvider> providers,
     SignatureHelpTriggerInfo triggerInfo)
 {
     ComputeModel(providers, SpecializedCollections.EmptyList<ISignatureHelpProvider>(), triggerInfo);
 }
Exemple #28
0
        protected override async Task <SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            if (!TryGetInitializerExpression(root, position, document.GetLanguageService <ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out var initializerExpression))
            {
                return(null);
            }

            var addMethods = await CommonSignatureHelpUtilities.GetCollectionInitializerAddMethodsAsync(
                document, initializerExpression, cancellationToken).ConfigureAwait(false);

            if (addMethods.IsDefaultOrEmpty)
            {
                return(null);
            }

            var textSpan    = SignatureHelpUtilities.GetSignatureHelpSpan(initializerExpression);
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            return(CreateCollectionInitializerSignatureHelpItems(addMethods.Select(s =>
                                                                                   ConvertMethodGroupMethod(document, s, initializerExpression.OpenBraceToken.SpanStart, semanticModel)).ToList(),
                                                                 textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
        }
        protected override async Task <SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ConstructorInitializerSyntax constructorInitializer;

            if (!TryGetConstructorInitializer(root, position, document.GetLanguageService <ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out constructorInitializer))
            {
                return(null);
            }

            var semanticModel = await document.GetCSharpSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var within = semanticModel.GetEnclosingNamedType(position, cancellationToken);

            if (within == null)
            {
                return(null);
            }

            if (within.TypeKind != TypeKind.Struct && within.TypeKind != TypeKind.Class)
            {
                return(null);
            }

            var type = constructorInitializer.Kind() == SyntaxKind.BaseConstructorInitializer
                ? within.BaseType
                : within;

            if (type == null)
            {
                return(null);
            }

            var symbolDisplayService   = document.Project.LanguageServices.GetService <ISymbolDisplayService>();
            var accessibleConstructors = type.InstanceConstructors
                                         .Where(c => c.IsAccessibleWithin(within))
                                         .Where(c => c.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation))
                                         .Sort(symbolDisplayService, semanticModel, constructorInitializer.SpanStart);

            if (!accessibleConstructors.Any())
            {
                return(null);
            }

            var anonymousTypeDisplayService           = document.Project.LanguageServices.GetService <IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService <IDocumentationCommentFormattingService>();
            var textSpan    = SignatureHelpUtilities.GetSignatureHelpSpan(constructorInitializer.ArgumentList);
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            return(CreateSignatureHelpItems(accessibleConstructors.Select(c =>
                                                                          Convert(c, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)),
                                            textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
        }
            private async Task<Tuple<ISignatureHelpProvider, SignatureHelpItems>> ComputeItemsAsync(
                IList<ISignatureHelpProvider> providers,
                SnapshotPoint caretPosition,
                SignatureHelpTriggerInfo triggerInfo,
                Document document,
                CancellationToken cancellationToken)
            {
                try
                {
                    ISignatureHelpProvider bestProvider = null;
                    SignatureHelpItems bestItems = null;

                    // TODO(cyrusn): We're calling into extensions, we need to make ourselves resilient
                    // to the extension crashing.
                    foreach (var provider in providers)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var currentItems = await provider.GetItemsAsync(document, caretPosition, triggerInfo, cancellationToken).ConfigureAwait(false);
                        if (currentItems != null && currentItems.ApplicableSpan.IntersectsWith(caretPosition.Position))
                        {
                            // If another provider provides sig help items, then only take them if they
                            // start after the last batch of items.  i.e. we want the set of items that
                            // conceptually are closer to where the caret position is.  This way if you have:
                            //
                            //  Foo(new Bar($$
                            //
                            // Then invoking sig help will only show the items for "new Bar(" and not also
                            // the items for "Foo(..."
                            if (IsBetter(bestItems, currentItems.ApplicableSpan))
                            {
                                bestItems = currentItems;
                                bestProvider = provider;
                            }
                        }
                    }

                    return Tuple.Create(bestProvider, bestItems);
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
                }
Exemple #31
0
        IEnumerable <INamedTypeSymbol> FindNearestTupleConstructionWithInferrableType(SyntaxNode root, SemanticModel semanticModel, int position, SignatureHelpTriggerInfo triggerInfo,
                                                                                      ITypeInferenceService typeInferrer, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken, out ExpressionSyntax targetExpression)
        {
            // Walk upward through TupleExpressionSyntax/ParenthsizedExpressionSyntax looking for a
            // place where we can infer a tuple type.
            ParenthesizedExpressionSyntax parenthesizedExpression = null;

            while (TryGetTupleExpression(triggerInfo.TriggerReason, root, position, syntaxFacts, cancellationToken, out var tupleExpression) ||
                   TryGetParenthesizedExpression(triggerInfo.TriggerReason, root, position, syntaxFacts, cancellationToken, out parenthesizedExpression))
            {
                targetExpression = (ExpressionSyntax)tupleExpression ?? parenthesizedExpression;
                var inferredTypes = typeInferrer.InferTypes(semanticModel, targetExpression.SpanStart, cancellationToken);

                var tupleTypes = inferredTypes.Where(t => t.IsTupleType).OfType <INamedTypeSymbol>().ToList();
                if (tupleTypes.Any())
                {
                    return(tupleTypes);
                }

                position = targetExpression.GetFirstToken().SpanStart;
            }

            targetExpression = null;
            return(null);
        }
        public async Task <ParameterHintingResult> GetParameterDataProviderAsync(List <ISignatureHelpProvider> providers, Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken token = default(CancellationToken))
        {
            var hintingData = new List <ParameterHintingData> ();
            SignatureHelpItems bestSignatureHelpItems = null;

            foreach (var provider in providers)
            {
                try {
                    if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.TypeCharCommand && !provider.IsTriggerCharacter(triggerInfo.TriggerCharacter.Value))
                    {
                        continue;
                    }
                    if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.RetriggerCommand && !provider.IsRetriggerCharacter(triggerInfo.TriggerCharacter.Value))
                    {
                        continue;
                    }
                    var signatureHelpItems = await provider.GetItemsAsync(document, position, triggerInfo, token).ConfigureAwait(false);

                    if (signatureHelpItems == null)
                    {
                        continue;
                    }
                    if (bestSignatureHelpItems == null)
                    {
                        bestSignatureHelpItems = signatureHelpItems;
                    }
                    else if (signatureHelpItems.ApplicableSpan.Start > bestSignatureHelpItems.ApplicableSpan.Start)
                    {
                        bestSignatureHelpItems = signatureHelpItems;
                    }
                } catch (Exception e) {
                    LoggingService.LogError("Error while getting items from parameter provider " + provider, e);
                }
            }

            if (bestSignatureHelpItems != null)
            {
                foreach (var item in bestSignatureHelpItems.Items)
                {
                    hintingData.Add(new SignatureHelpParameterHintingData(item));
                }
                var tree = await document.GetSyntaxTreeAsync(token);

                var tokenLeftOfPosition = tree.GetRoot(token).FindTokenOnLeftOfPosition(position);
                var syntaxNode          = tokenLeftOfPosition.Parent;
                var node = syntaxNode?.FirstAncestorOrSelf <ArgumentListSyntax> ();
                return(new ParameterHintingResult(hintingData)
                {
                    ApplicableSpan = bestSignatureHelpItems.ApplicableSpan,
                    SelectedItemIndex = bestSignatureHelpItems.SelectedItemIndex,
                    ParameterListStart = node != null ? node.SpanStart : bestSignatureHelpItems.ApplicableSpan.Start
                });
            }
            return(ParameterHintingResult.Empty);
        }
        protected override async Task <SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            InvocationExpressionSyntax invocationExpression;

            if (!TryGetInvocationExpression(root, position, document.GetLanguageService <ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out invocationExpression))
            {
                return(null);
            }

            var semanticModel = await document.GetSemanticModelForNodeAsync(invocationExpression, cancellationToken).ConfigureAwait(false);

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);

            if (within == null)
            {
                return(null);
            }

            // get the regular signature help items
            var symbolDisplayService = document.Project.LanguageServices.GetService <ISymbolDisplayService>();
            var methodGroup          = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken)
                                       .OfType <IMethodSymbol>()
                                       .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation);

            // try to bind to the actual method
            var symbolInfo          = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken);
            var matchedMethodSymbol = symbolInfo.Symbol as IMethodSymbol;

            // if the symbol could be bound, replace that item in the symbol list
            if (matchedMethodSymbol != null && matchedMethodSymbol.IsGenericMethod)
            {
                methodGroup = methodGroup.Select(m => matchedMethodSymbol.OriginalDefinition == m ? matchedMethodSymbol : m);
            }

            methodGroup = methodGroup.Sort(symbolDisplayService, semanticModel, invocationExpression.SpanStart);

            var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol;

            var anonymousTypeDisplayService           = document.Project.LanguageServices.GetService <IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService <IDocumentationCommentFormattingService>();

            var textSpan    = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList);
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (methodGroup.Any())
            {
                return(CreateSignatureHelpItems(
                           GetMethodGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, cancellationToken),
                           textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
            }
            else if (expressionType != null && expressionType.TypeKind == TypeKind.Delegate)
            {
                return(CreateSignatureHelpItems(
                           GetDelegateInvokeItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, expressionType, cancellationToken),
                           textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
            }
            else
            {
                return(null);
            }
        }
        private static async Task <SignatureHelpState> GetArgumentStateAsync(int cursorPosition, Document document, ISignatureHelpProvider signatureHelpProvider, SignatureHelpTriggerInfo triggerInfo)
        {
            var items = await signatureHelpProvider.GetItemsAsync(document, cursorPosition, triggerInfo, CancellationToken.None);

            return(items == null ? null : new SignatureHelpState(items.ArgumentIndex, items.ArgumentCount, items.ArgumentName, null));
        }
        public async Task<SignatureHelpItems> GetItemsAsync(
            Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var itemsForCurrentDocument = await GetItemsWorkerAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);
            if (itemsForCurrentDocument == null)
            {
                return itemsForCurrentDocument;
            }

            var relatedDocuments = document.GetLinkedDocumentIds();
            if (!relatedDocuments.Any())
            {
                return itemsForCurrentDocument;
            }

            var relatedDocumentsAndItems = await GetItemsForRelatedDocuments(document, relatedDocuments, position, triggerInfo, cancellationToken).ConfigureAwait(false);
            var candidateLinkedProjectsAndSymbolSets = await ExtractSymbolsFromRelatedItems(position, relatedDocumentsAndItems, cancellationToken).ConfigureAwait(false);

            var totalProjects = candidateLinkedProjectsAndSymbolSets.Select(c => c.Item1).Concat(document.Project.Id);

            var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false);
            var compilation = semanticModel.Compilation;
            var finalItems = new List<SignatureHelpItem>();
            foreach (var item in itemsForCurrentDocument.Items)
            {
                var symbolKey = ((SymbolKeySignatureHelpItem)item).SymbolKey;
                if (symbolKey == null)
                {
                    finalItems.Add(item);
                    continue;
                }

                var expectedSymbol = symbolKey.Resolve(compilation, ignoreAssemblyKey: true, cancellationToken: cancellationToken).Symbol;

                if (expectedSymbol == null)
                {
                    finalItems.Add(item);
                    continue;
                }

                var invalidProjectsForCurrentSymbol = candidateLinkedProjectsAndSymbolSets.Where(c => !c.Item2.Contains(expectedSymbol, LinkedFilesSymbolEquivalenceComparer.IgnoreAssembliesInstance))
                                                                        .Select(c => c.Item1)
                                                                        .ToList();

                var platformData = new SupportedPlatformData(invalidProjectsForCurrentSymbol, totalProjects, document.Project.Solution.Workspace);
                finalItems.Add(UpdateItem(item, platformData, expectedSymbol));
            }

            return new SignatureHelpItems(
                finalItems, itemsForCurrentDocument.ApplicableSpan,
                itemsForCurrentDocument.ArgumentIndex,
                itemsForCurrentDocument.ArgumentCount,
                itemsForCurrentDocument.ArgumentName,
                itemsForCurrentDocument.SelectedItemIndex);
        }
            private async Task<Model> ComputeModelInBackgroundAsync(
                Model currentModel,
                IList<ISignatureHelpProvider> matchedProviders,
                IList<ISignatureHelpProvider> unmatchedProviders,
                SnapshotPoint caretPosition,
                DisconnectedBufferGraph disconnectedBufferGraph,
                SignatureHelpTriggerInfo triggerInfo,
                CancellationToken cancellationToken)
            {
                try
                {
                    using (Logger.LogBlock(FunctionId.SignatureHelp_ModelComputation_ComputeModelInBackground, cancellationToken))
                    {
                        AssertIsBackground();
                        cancellationToken.ThrowIfCancellationRequested();

                        var document = await Controller.DocumentProvider.GetDocumentAsync(caretPosition.Snapshot, cancellationToken).ConfigureAwait(false);
                        if (document == null)
                        {
                            return currentModel;
                        }

                        if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.RetriggerCommand)
                        {
                            if (currentModel == null ||
                                (triggerInfo.TriggerCharacter.HasValue && !currentModel.Provider.IsRetriggerCharacter(triggerInfo.TriggerCharacter.Value)))
                            {
                                return currentModel;
                            }
                        }

                        // first try to query the providers that can trigger on the specified character
                        var result = await ComputeItemsAsync(matchedProviders, caretPosition, triggerInfo, document, cancellationToken).ConfigureAwait(false);
                        var provider = result.Item1;
                        var items = result.Item2;

                        if (provider == null)
                        {
                            // no match, so now query the other providers
                            result = await ComputeItemsAsync(unmatchedProviders, caretPosition, triggerInfo, document, cancellationToken).ConfigureAwait(false);
                            provider = result.Item1;
                            items = result.Item2;

                            if (provider == null)
                            {
                                // the other providers didn't produce items either, so we don't produce a model
                                return null;
                            }
                        }

                        if (currentModel != null &&
                            currentModel.Provider == provider &&
                            currentModel.GetCurrentSpanInSubjectBuffer(disconnectedBufferGraph.SubjectBufferSnapshot).Span.Start == items.ApplicableSpan.Start &&
                            currentModel.ArgumentIndex == items.ArgumentIndex &&
                            currentModel.ArgumentCount == items.ArgumentCount &&
                            currentModel.ArgumentName == items.ArgumentName)
                        {
                            // The new model is the same as the current model.  Return the currentModel
                            // so we keep the active selection.
                            return currentModel;
                        }

                        var selectedItem = GetSelectedItem(currentModel, items, provider);
                        var model = new Model(disconnectedBufferGraph, items.ApplicableSpan, provider,
                            items.Items, selectedItem, items.ArgumentIndex, items.ArgumentCount, items.ArgumentName,
                            selectedParameter: 0);

                        var syntaxFactsService = document.GetLanguageService<ISyntaxFactsService>();
                        var isCaseSensitive = syntaxFactsService == null || syntaxFactsService.IsCaseSensitive;
                        var selection = DefaultSignatureHelpSelector.GetSelection(model.Items,
                            model.SelectedItem, model.ArgumentIndex, model.ArgumentCount, model.ArgumentName, isCaseSensitive);

                        return model.WithSelectedItem(selection.SelectedItem)
                                    .WithSelectedParameter(selection.SelectedParameter);
                    }
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
                }
        protected async Task<List<Tuple<Document, IEnumerable<SignatureHelpItem>>>> GetItemsForRelatedDocuments(Document document, IEnumerable<DocumentId> relatedDocuments, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var supportedPlatforms = new List<Tuple<Document, IEnumerable<SignatureHelpItem>>>();
            foreach (var relatedDocumentId in relatedDocuments)
            {
                var relatedDocument = document.Project.Solution.GetDocument(relatedDocumentId);
                var semanticModel = await relatedDocument.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false);
                var result = await GetItemsWorkerAsync(relatedDocument, position, triggerInfo, cancellationToken).ConfigureAwait(false);

                supportedPlatforms.Add(Tuple.Create(relatedDocument, result != null ? result.Items : SpecializedCollections.EmptyEnumerable<SignatureHelpItem>()));
            }

            return supportedPlatforms;
        }
        protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxToken genericIdentifier, lessThanToken;
            if (!TryGetGenericIdentifier(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken,
                    out genericIdentifier, out lessThanToken))
            {
                return null;
            }

            var simpleName = genericIdentifier.Parent as SimpleNameSyntax;
            if (simpleName == null)
            {
                return null;
            }

            var beforeDotExpression = simpleName.IsRightSideOfDot() ? simpleName.GetLeftSideOfDot() : null;

            var semanticModel = await document.GetSemanticModelForNodeAsync(simpleName, cancellationToken).ConfigureAwait(false);

            var leftSymbol = beforeDotExpression == null
                ? null
                : semanticModel.GetSymbolInfo(beforeDotExpression, cancellationToken).GetAnySymbol() as INamespaceOrTypeSymbol;
            var leftType = beforeDotExpression == null
                ? null
                : semanticModel.GetTypeInfo(beforeDotExpression, cancellationToken).Type as INamespaceOrTypeSymbol;

            var leftContainer = leftSymbol ?? leftType;

            var isBaseAccess = beforeDotExpression is BaseExpressionSyntax;
            var namespacesOrTypesOnly = SyntaxFacts.IsInNamespaceOrTypeContext(simpleName);
            var includeExtensions = leftSymbol == null && leftType != null;
            var name = genericIdentifier.ValueText;
            var symbols = isBaseAccess
                ? semanticModel.LookupBaseMembers(position, name)
                : namespacesOrTypesOnly
                    ? semanticModel.LookupNamespacesAndTypes(position, leftContainer, name)
                    : semanticModel.LookupSymbols(position, leftContainer, name, includeExtensions);

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within == null)
            {
                return null;
            }

            var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>();
            var accessibleSymbols =
                symbols.Where(s => s.GetArity() > 0)
                       .Where(s => s is INamedTypeSymbol || s is IMethodSymbol)
                       .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                       .Sort(symbolDisplayService, semanticModel, genericIdentifier.SpanStart);

            if (!accessibleSymbols.Any())
            {
                return null;
            }

            var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>();
            var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>();
            var textSpan = GetTextSpan(genericIdentifier, lessThanToken);
            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

            return CreateSignatureHelpItems(accessibleSymbols.Select(s =>
                Convert(s, lessThanToken, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)),
                textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken));
        }
Exemple #39
0
        protected override async Task <SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            AttributeSyntax attribute;

            if (!TryGetAttributeExpression(root, position, document.GetLanguageService <ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out attribute))
            {
                return(null);
            }

            var semanticModel = await document.GetSemanticModelForNodeAsync(attribute, cancellationToken).ConfigureAwait(false);

            var attributeType = semanticModel.GetTypeInfo(attribute, cancellationToken).Type as INamedTypeSymbol;

            if (attributeType == null)
            {
                return(null);
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);

            if (within == null)
            {
                return(null);
            }

            var symbolDisplayService   = document.Project.LanguageServices.GetService <ISymbolDisplayService>();
            var accessibleConstructors = attributeType.InstanceConstructors
                                         .Where(c => c.IsAccessibleWithin(within))
                                         .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)
                                         .Sort(symbolDisplayService, semanticModel, attribute.SpanStart);

            if (!accessibleConstructors.Any())
            {
                return(null);
            }

            var anonymousTypeDisplayService   = document.Project.LanguageServices.GetService <IAnonymousTypeDisplayService>();
            var documentationCommentFormatter = document.Project.LanguageServices.GetService <IDocumentationCommentFormattingService>();
            var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(attribute.ArgumentList);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            return(CreateSignatureHelpItems(accessibleConstructors.Select(c =>
                                                                          Convert(c, within, attribute, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormatter, cancellationToken)),
                                            textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)));
        }
		public async Task<SignatureHelpResult> GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken)) {
			var res = await ComputeItemsAsync(signatureHelpProviders, position, triggerInfo.ToSignatureHelpTriggerInfo(), document, cancellationToken).ConfigureAwait(false);
			return GetSignatureHelpResult(res, document);
		}