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<CompletionItem> GetBuilderAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken)) { if (triggerInfo.TriggerReason == CompletionTriggerReason.TypeCharCommand) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (triggerInfo.IsDebugger) { // Aggressive Intellisense in the debugger: always show the builder return CreateEmptyBuilder(text, position); } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.LambdaExpression, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token)) { return CreateBuilder(text, position, CSharpFeaturesResources.MemberName, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptyBuilder(text, position); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateBuilder(text, position, CSharpFeaturesResources.ImplicitArrayCreation, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateBuilder(text, position, CSharpFeaturesResources.RangeVariable, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } } return null; }
protected override async Task<CompletionItem> GetSuggestionModeItemAsync(Document document, int position, TextSpan itemSpan, CompletionTrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) { if (trigger.Kind == CompletionTriggerKind.Insertion) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.LambdaExpression, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialLambdaDeclaration); } else if (IsAnonymousObjectCreation(token) || IsPossibleTupleExpression(token)) { return CreateSuggestionModeItem(CSharpFeaturesResources.MemberName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPossibleExplicitlyNamesAnonTypeMemCreation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptySuggestionModeItem(itemSpan); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.ImplicitArrayCreation, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialImplicitArray); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateSuggestionModeItem(CSharpFeaturesResources.RangeVariable, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToPotentialRangeVariableDecl); } else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.NamespaceName, itemSpan, CSharpFeaturesResources.AutoselectDisabledDueToNamespaceDeclaration); } } return null; }
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 .WhereAsArray(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)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
protected override async Task<CompletionItem> GetSuggestionModeItemAsync( Document document, int position, TextSpan itemSpan, CompletionTrigger trigger, CancellationToken cancellationToken = default(CancellationToken)) { if (trigger.Kind == CompletionTriggerKind.Insertion) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var token = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (token.Kind() == SyntaxKind.None) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var typeInferrer = document.GetLanguageService<ITypeInferenceService>(); if (IsLambdaExpression(semanticModel, position, token, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.lambda_expression, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_lambda_declaration); } else if (IsAnonymousObjectCreation(token)) { return CreateSuggestionModeItem(CSharpFeaturesResources.member_name, CSharpFeaturesResources.Autoselect_disabled_due_to_possible_explicitly_named_anonymous_type_member_creation); } else if (token.IsPreProcessorExpressionContext()) { return CreateEmptySuggestionModeItem(); } else if (IsImplicitArrayCreation(semanticModel, token, position, typeInferrer, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.implicit_array_creation, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_implicit_array_creation); } else if (token.IsKindOrHasMatchingText(SyntaxKind.FromKeyword) || token.IsKindOrHasMatchingText(SyntaxKind.JoinKeyword)) { return CreateSuggestionModeItem(CSharpFeaturesResources.range_variable, CSharpFeaturesResources.Autoselect_disabled_due_to_potential_range_variable_declaration); } else if (tree.IsNamespaceDeclarationNameContext(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.namespace_name, CSharpFeaturesResources.Autoselect_disabled_due_to_namespace_declaration); } else if (tree.IsPartialTypeDeclarationNameContext(position, cancellationToken, out var typeDeclaration)) { switch (typeDeclaration.Keyword.Kind()) { case SyntaxKind.ClassKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.class_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); case SyntaxKind.StructKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.struct_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); case SyntaxKind.InterfaceKeyword: return CreateSuggestionModeItem(CSharpFeaturesResources.interface_name, CSharpFeaturesResources.Autoselect_disabled_due_to_type_declaration); } } else if (tree.IsPossibleDeconstructionDesignation(position, cancellationToken)) { return CreateSuggestionModeItem(CSharpFeaturesResources.designation_name, CSharpFeaturesResources.Autoselect_disabled_due_to_possible_deconstruction_declaration); } } return null; }
protected override async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync( Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return null; } var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (token.Kind() != SyntaxKind.OpenParenToken && token.Kind() != SyntaxKind.CommaToken) { return null; } var attributeArgumentList = token.Parent as AttributeArgumentListSyntax; var attributeSyntax = token.Parent.Parent as AttributeSyntax; if (attributeSyntax == null || attributeArgumentList == null) { return null; } // We actually want to collect two sets of named parameters to present the user. The // normal named parameters that come from the attribute constructors. These will be // presented like "foo:". And also the named parameters that come from the writable // fields/properties in the attribute. These will be presented like "bar =". var existingNamedParameters = GetExistingNamedParameters(attributeArgumentList, position); var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForNodeAsync(attributeSyntax, cancellationToken).ConfigureAwait(false); var nameColonItems = await GetNameColonItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); var nameEqualsItems = await GetNameEqualsItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); // If we're after a name= parameter, then we only want to show name= parameters. if (IsAfterNameEqualsArgument(token)) { return nameEqualsItems; } return nameColonItems.Concat(nameEqualsItems); }
protected override async Task<bool> IsExclusiveAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { // We're exclusive if this context could only be an object initializer and not also a // collection initializer. If we're initializing something that could be initialized as // an object or as a collection, say we're not exclusive. That way the rest of // intellisense can be used in the collection intializer. // // Consider this case: // class c : IEnumerable<int> // { // public void Add(int addend) { } // public int foo; // } // void foo() // { // var b = new c {| // } // There we could initialize b using either an object initializer or a collection // initializer. Since we don't know which the user will use, we'll be non-exclusive, so // the other providers can help the user write the collection initializer, if they want // to. var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return false; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (token.Parent == null) { return false; } var expression = token.Parent.Parent as ExpressionSyntax; if (expression == null) { return false; } var semanticModel = await document.GetSemanticModelForNodeAsync(expression, cancellationToken).ConfigureAwait(false); var initializedType = semanticModel.GetTypeInfo(expression, cancellationToken).Type; if (initializedType == null) { return false; } // Non-exclusive if initializedType can be initialized as a collection. if (initializedType.CanSupportCollectionInitializer()) { return false; } // By default, only our member names will show up. return true; }
public static Task <SemanticModel> GetCSharpSemanticModelForNodeAsync(this Document document, SyntaxNode node, CancellationToken cancellationToken = default(CancellationToken)) { return(document.GetSemanticModelForNodeAsync(node, cancellationToken)); }
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)).ToList(), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); }
private async Task<ValueTuple<SemanticModel, IList<ISymbol>>> BindTokenAsync( Document document, SyntaxToken token, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(false); var enclosingType = semanticModel.GetEnclosingNamedType(token.SpanStart, cancellationToken); var symbols = semanticModel.GetSymbols(token, document.Project.Solution.Workspace, bindLiteralsToUnderlyingType: true, cancellationToken: cancellationToken); var bindableParent = document.GetLanguageService<ISyntaxFactsService>().GetBindableParent(token); var overloads = semanticModel.GetMemberGroup(bindableParent, cancellationToken); symbols = symbols.Where(IsOk) .Where(s => IsAccessible(s, enclosingType)) .Concat(overloads) .Distinct(SymbolEquivalenceComparer.Instance); if (symbols.Any()) { var typeParameter = symbols.First() as ITypeParameterSymbol; return new ValueTuple<SemanticModel, IList<ISymbol>>( semanticModel, typeParameter != null && typeParameter.TypeParameterKind == TypeParameterKind.Cref ? SpecializedCollections.EmptyList<ISymbol>() : symbols.ToList()); } // Couldn't bind the token to specific symbols. If it's an operator, see if we can at // least bind it to a type. var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>(); if (syntaxFacts.IsOperator(token)) { var typeInfo = semanticModel.GetTypeInfo(token.Parent, cancellationToken); if (IsOk(typeInfo.Type)) { return new ValueTuple<SemanticModel, IList<ISymbol>>(semanticModel, new List<ISymbol>(1) { typeInfo.Type }); } } return ValueTuple.Create(semanticModel, SpecializedCollections.EmptyList<ISymbol>()); }