public static async Task <CompletionDescription> GetDescriptionAsync( CompletionItem item, Document document, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var position = GetDescriptionPosition(item); if (position == -1) { position = item.Span.Start; } var supportedPlatforms = GetSupportedPlatforms(item, workspace); var contextDocument = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms); var semanticModel = await contextDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var symbols = await GetSymbolsAsync(item, document, cancellationToken).ConfigureAwait(false); if (symbols.Length > 0) { return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false)); } else { return(CompletionDescription.Empty); } }
internal static TextSpan GetCompletionItemSpan(SourceText text, int position) => CommonCompletionUtilities.GetWordSpan( text, position, IsCompletionItemStartCharacter, IsWordCharacter );
public static async Task <CompletionDescription> GetDescriptionAsync( CompletionItem item, IReadOnlyList <ISymbol> symbols, Document document, SemanticModel semanticModel, CancellationToken cancellationToken ) { var workspace = document.Project.Solution.Workspace; var position = GetDescriptionPosition(item); var supportedPlatforms = GetSupportedPlatforms(item, workspace); if (symbols.Count != 0) { return(await CommonCompletionUtilities .CreateDescriptionAsync( workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken ) .ConfigureAwait(false)); } else { return(CompletionDescription.Empty); } }
public static async Task <CompletionDescription> GetCompletionDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken) { var metadataName = GetMetadataName(item); if (!string.IsNullOrEmpty(metadataName)) { var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var symbol = compilation.GetTypeByMetadataName(metadataName); if (symbol != null) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // We choose not to display the number of "type overloads" for simplicity. // Otherwise, we need additonal logic to track internal and public visible // types separately, and cache both completion items. return(await CommonCompletionUtilities.CreateDescriptionAsync( document.Project.Solution.Workspace, semanticModel, position : 0, symbol, overloadCount : 0, supportedPlatforms : null, cancellationToken).ConfigureAwait(false)); } } return(null); }
private async Task <CompletionItem> CreateItemAsync( Workspace workspace, SemanticModel semanticModel, int textChangeSpanPosition, ISymbol symbol, SyntaxToken token, CancellationToken cancellationToken) { int tokenPosition = token.SpanStart; string symbolText = string.Empty; if (symbol is INamespaceOrTypeSymbol && token.IsKind(SyntaxKind.DotToken)) { symbolText = symbol.Name.EscapeIdentifier(); if (symbol.GetArity() > 0) { symbolText += "{"; symbolText += string.Join(", ", ((INamedTypeSymbol)symbol).TypeParameters); symbolText += "}"; } } else { symbolText = symbol.ToMinimalDisplayString(semanticModel, tokenPosition, CrefFormat); var parameters = symbol.GetParameters().Select(p => { var displayName = p.Type.ToMinimalDisplayString(semanticModel, tokenPosition); if (p.RefKind == RefKind.Out) { return("out " + displayName); } if (p.RefKind == RefKind.Ref) { return("ref " + displayName); } return(displayName); }); var parameterList = !symbol.IsIndexer() ? string.Format("({0})", string.Join(", ", parameters)) : string.Format("[{0}]", string.Join(", ", parameters)); symbolText += parameterList; } var insertionText = symbolText .Replace('<', '{') .Replace('>', '}') .Replace("()", ""); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return(new CrefCompletionItem( workspace, completionProvider: this, displayText: insertionText, insertionText: insertionText, textSpan: GetTextChangeSpan(text, textChangeSpanPosition), descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, tokenPosition, symbol), glyph: symbol.GetGlyph(), sortText: symbolText)); }
private static TextSpan GetCompletionItemSpan(SourceText text, int position) { return(CommonCompletionUtilities.GetWordSpan( text, position, ch => CompletionUtilities.IsCompletionItemStartCharacter(ch) || ch == '{', ch => CompletionUtilities.IsWordCharacter(ch) || ch == '{' || ch == '}')); }
private TextSpan GetTextChangeSpan(SourceText text, int position) { return(CommonCompletionUtilities.GetTextChangeSpan( text, position, (ch) => CompletionUtilities.IsTextChangeSpanStartCharacter(ch) || ch == '{', (ch) => CompletionUtilities.IsWordCharacter(ch) || ch == '{' || ch == '}')); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, length : 0), cancellationToken).ConfigureAwait(false); var typeAndLocation = GetInitializedType(document, semanticModel, position, cancellationToken); if (typeAndLocation == null) { return; } var initializedType = typeAndLocation.Item1 as INamedTypeSymbol; var initializerLocation = typeAndLocation.Item2; if (initializedType == null) { return; } if (await IsExclusiveAsync(document, position, cancellationToken).ConfigureAwait(false)) { context.MakeExclusive(true); } var enclosing = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members. IEnumerable <ISymbol> members = semanticModel.LookupSymbols(position, initializedType); members = members.Where(m => IsInitializable(m, initializedType) && m.CanBeReferencedByName && IsLegalFieldOrProperty(m, enclosing) && !m.IsImplicitlyDeclared); // Filter out those members that have already been typed var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var filterSpan = GetTextChangeSpan(text, position); foreach (var uninitializedMember in uninitializedMembers) { context.AddItem(CreateItem( workspace, uninitializedMember.Name, filterSpan, CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, initializerLocation.SourceSpan.Start, uninitializedMember), uninitializedMember.GetGlyph())); } }
public static bool IsStartingNewWord(SourceText text, int characterPosition) { return(CommonCompletionUtilities.IsStartingNewWord( text, characterPosition, IsWordStartCharacter, IsWordCharacter )); }
internal static bool IsTriggerCharacter(SourceText text, int characterPosition) { // Bring up completion when the user types a quote (i.e.: #r "), or if they type a slash // path separator character, or if they type a comma (#r "foo,version..."). // // Also, if they're starting a word. i.e. #r "c:\W var ch = text[characterPosition]; return(ch == '"' || ch == '\\' || ch == ',' || CommonCompletionUtilities.IsStartingNewWord(text, characterPosition, char.IsLetter, char.IsLetterOrDigit)); }
public CompletionHandler( IGlobalOptionService globalOptions, [ImportMany] IEnumerable <Lazy <CompletionProvider, CompletionProviderMetadata> > completionProviders) { _globalOptions = globalOptions; _csharpTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.CSharp).SelectMany( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet(); _vbTriggerCharacters = completionProviders.Where(lz => lz.Metadata.Language == LanguageNames.VisualBasic).SelectMany( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).ToImmutableHashSet(); }
public override async Task <ImmutableArray <SymbolDisplayPart> > GetDescriptionAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (this.LazyDescription == null) { Interlocked.CompareExchange( ref this.LazyDescription, new AsyncLazy <ImmutableArray <SymbolDisplayPart> >( CommonCompletionUtilities.CreateDescriptionFactory(this.Context.Workspace, this.Context.SemanticModel, this.Position, this.Symbols, this.supportedPlatorms), cacheResult: true), null); } return(await base.GetDescriptionAsync(cancellationToken).ConfigureAwait(false)); }
public static string GetInsertionText(ISymbol symbol, SyntaxContext context) { if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, out var name)) { // Cannot escape Attribute name with the suffix removed. Only use the name with // the suffix removed if it does not need to be escaped. if (name.Equals(name.EscapeIdentifier())) { return(name); } } return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery)); }
public static string GetInsertionText(ISymbol symbol, AbstractSyntaxContext context) { string name; if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context.IsAttributeNameContext, context.GetLanguageService <ISyntaxFactsService>(), out name)) { // Cannot escape Attribute name with the suffix removed. Only use the name with // the suffix removed if it does not need to be escaped. if (name.Equals(name.EscapeIdentifier())) { return(name); } } return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery)); }
private CompletionItem CreateItem(IMethodSymbol method, int line, TextSpan lineSpan, TextSpan span, SemanticModel semanticModel, DeclarationModifiers modifiers, Document document, SyntaxToken token) { modifiers = new DeclarationModifiers(method.IsStatic, isUnsafe: method.IsUnsafe(), isPartial: true, isAsync: modifiers.IsAsync); var displayText = GetDisplayText(method, semanticModel, span.Start); return(new MemberInsertionCompletionItem( this, displayText, span, CommonCompletionUtilities.CreateDescriptionFactory(document.Project.Solution.Workspace, semanticModel, span.Start, method), Glyph.MethodPrivate, modifiers, line, method.GetSymbolKey(), token)); }
public static async Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, ImmutableArray <ISymbol> symbols, Document document, SemanticModel semanticModel, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var position = SymbolCompletionItem.GetDescriptionPosition(item); var supportedPlatforms = SymbolCompletionItem.GetSupportedPlatforms(item, workspace); var contextDocument = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms); if (symbols.Length != 0) { return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false)); } else { return(CompletionDescription.Empty); } }
private MemberInsertionCompletionItem CreateItem( ISymbol symbol, TextSpan textChangeSpan, ISymbolDisplayService symbolDisplayService, SemanticModel semanticModel, SyntaxToken startToken, DeclarationModifiers modifiers) { var position = startToken.SpanStart; var displayString = symbolDisplayService.ToMinimalDisplayString(semanticModel, position, symbol, _overrideNameFormat); return(new MemberInsertionCompletionItem(_provider, displayString, textChangeSpan, CommonCompletionUtilities.CreateDescriptionFactory(_document.Project.Solution.Workspace, semanticModel, position, symbol), symbol.GetGlyph(), modifiers, _startLineNumber, symbol.GetSymbolKey(), startToken)); }
protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false); var typeAndLocation = GetInitializedType(document, semanticModel, position, cancellationToken); if (typeAndLocation == null) { return(null); } var initializedType = typeAndLocation.Item1 as INamedTypeSymbol; var initializerLocation = typeAndLocation.Item2; if (initializedType == null) { return(null); } // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members. IEnumerable <ISymbol> members = semanticModel.LookupSymbols(position, initializedType); members = members.Where(m => IsInitializable(m, initializedType) && m.CanBeReferencedByName && IsLegalFieldOrProperty(m) && !m.IsImplicitlyDeclared); // Filter out those members that have already been typed var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var changes = GetTextChangeSpan(text, position); // Return the members return(uninitializedMembers.Select( m => CreateItem(workspace, m.Name, changes, CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, initializerLocation.SourceSpan.Start, m), m.GetGlyph()))); }
private async Task <IEnumerable <CompletionItem> > GetNameEqualsItemsAsync(Workspace workspace, SemanticModel semanticModel, int position, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters, CancellationToken cancellationToken) { var attributeNamedParameters = GetAttributeNamedParameters(semanticModel, position, attributeSyntax, cancellationToken); var unspecifiedNamedParameters = attributeNamedParameters.Where(p => !existingNamedParameters.Contains(p.Name)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return(from p in attributeNamedParameters where !existingNamedParameters.Contains(p.Name) select new CompletionItem( this, p.Name.ToIdentifierToken().ToString() + SpaceEqualsString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name, rules: ItemRules.Instance)); }
public static string GetInsertionText(ISymbol symbol, SyntaxContext context) { if (CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, out var name)) { // Cannot escape Attribute name with the suffix removed. Only use the name with // the suffix removed if it does not need to be escaped. if (name.Equals(name.EscapeIdentifier())) { return(name); } } if (symbol.Kind == SymbolKind.Label && symbol.DeclaringSyntaxReferences[0].GetSyntax().Kind() == SyntaxKind.DefaultSwitchLabel) { return(symbol.Name); } return(symbol.Name.EscapeIdentifier(isQueryContext: context.IsInQuery)); }
private static async Task <TextSpan> GetTextChangeSpanAsync(Document document, TextSpan startSpan, CancellationToken cancellationToken) { var result = startSpan; var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(result.Start); if (syntaxFacts.IsStringLiteral(token) || syntaxFacts.IsVerbatimStringLiteral(token)) { var text = root.GetText(); // Expand selection in both directions until a double quote or any line break character is reached bool IsWordCharacter(char ch) => !(ch == '"' || TextUtilities.IsAnyLineBreakCharacter(ch)); result = CommonCompletionUtilities.GetWordSpan( text, startSpan.Start, IsWordCharacter, IsWordCharacter, alwaysExtendEndSpan: true); } return(result); }
public static async Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, Document document, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var position = GetDescriptionPosition(item); if (position == -1) { position = item.Span.Start; } var supportedPlatforms = GetSupportedPlatforms(item, workspace); // find appropriate document for descripton context var contextDocument = document; if (supportedPlatforms != null && supportedPlatforms.InvalidProjects.Contains(document.Id.ProjectId)) { var contextId = document.GetLinkedDocumentIds().FirstOrDefault(id => !supportedPlatforms.InvalidProjects.Contains(id.ProjectId)); if (contextId != null) { contextDocument = document.Project.Solution.GetDocument(contextId); } } var semanticModel = await contextDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var symbols = await GetSymbolsAsync(item, document, cancellationToken).ConfigureAwait(false); if (symbols.Length > 0) { return(await CommonCompletionUtilities.CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms, cancellationToken).ConfigureAwait(false)); } else { return(CompletionDescription.Empty); } }
private async Task <IEnumerable <CompletionItem> > GetNameColonItemsAsync( Workspace workspace, SemanticModel semanticModel, int position, SyntaxToken token, AttributeSyntax attributeSyntax, ISet <string> existingNamedParameters, CancellationToken cancellationToken) { var parameterLists = GetParameterLists(semanticModel, position, attributeSyntax, cancellationToken); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); return (from pl in parameterLists from p in pl where !existingNamedParameters.Contains(p.Name) select new CSharpCompletionItem( workspace, this, p.Name.ToIdentifierToken().ToString() + ColonString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name)); }
public static async Task <CompletionDescription> GetDescriptionForSymbolsAsync( CompletionItem item, Document document, ImmutableArray <ISymbol> symbols, SymbolDescriptionOptions options, CancellationToken cancellationToken) { if (symbols.Length == 0) { return(CompletionDescription.Empty); } var position = GetDescriptionPosition(item); if (position == -1) { position = item.Span.Start; } var supportedPlatforms = GetSupportedPlatforms(item, document.Project.Solution); var contextDocument = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms); var semanticModel = await contextDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var services = document.Project.Solution.Services; return(await CommonCompletionUtilities.CreateDescriptionAsync(services, semanticModel, position, symbols, options, supportedPlatforms, cancellationToken).ConfigureAwait(false)); }
protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync( Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return(null); } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return(null); } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var type = typeInferenceService.InferType(semanticModel, position, objectAsDefault: true, cancellationToken: cancellationToken); // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { return(null); } } if (type.TypeKind != TypeKind.Enum) { type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return(null); } } if (!type.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation)) { return(null); } // Does type have any aliases? ISymbol alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayService = document.GetLanguageService <ISymbolDisplayService>(); var displayText = alias != null ? alias.Name : displayService.ToMinimalDisplayString(semanticModel, position, type); var workspace = document.Project.Solution.Workspace; var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); var item = new CSharpCompletionItem( workspace, this, displayText: displayText, filterSpan: textChangeSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, alias ?? type), glyph: (alias ?? type).GetGlyph(), preselect: true); return(SpecializedCollections.SingletonEnumerable(item)); }
public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { var capabilities = new ServerCapabilities(); if (clientCapabilities is VSInternalClientCapabilities vsClientCapabilities && vsClientCapabilities.SupportsVisualStudioExtensions) { capabilities = GetVSServerCapabilities(); } var commitCharacters = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray(); var triggerCharacters = _completionProviders.SelectMany( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray(); capabilities.DefinitionProvider = true; capabilities.RenameProvider = true; capabilities.ImplementationProvider = true; capabilities.CodeActionProvider = new CodeActionOptions { CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor }, ResolveProvider = true }; capabilities.CompletionProvider = new VisualStudio.LanguageServer.Protocol.CompletionOptions { ResolveProvider = true, AllCommitCharacters = commitCharacters, TriggerCharacters = triggerCharacters, }; capabilities.SignatureHelpProvider = new SignatureHelpOptions { TriggerCharacters = new[] { "(", "," } }; capabilities.DocumentSymbolProvider = true; capabilities.WorkspaceSymbolProvider = true; capabilities.DocumentFormattingProvider = true; capabilities.DocumentRangeFormattingProvider = true; capabilities.DocumentOnTypeFormattingProvider = new DocumentOnTypeFormattingOptions { FirstTriggerCharacter = "}", MoreTriggerCharacter = new[] { ";", "\n" } }; capabilities.ReferencesProvider = true; capabilities.FoldingRangeProvider = true; capabilities.ExecuteCommandProvider = new ExecuteCommandOptions(); capabilities.TextDocumentSync = new TextDocumentSyncOptions { Change = TextDocumentSyncKind.Incremental, OpenClose = true }; capabilities.HoverProvider = true; capabilities.SemanticTokensOptions = new SemanticTokensOptions { Full = new SemanticTokensFullOptions { Delta = true }, Range = true, Legend = new SemanticTokensLegend { TokenTypes = SemanticTokenTypes.AllTypes.Concat(SemanticTokensHelpers.RoslynCustomTokenTypes).ToArray(), TokenModifiers = new string[] { SemanticTokenModifiers.Static } } }; return(capabilities); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { try { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return; } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var type = typeInferenceService.InferType(semanticModel, position, objectAsDefault: true, cancellationToken: cancellationToken); // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { return; } } if (type.TypeKind != TypeKind.Enum) { type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return; } } if (!type.IsEditorBrowsable(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation)) { return; } // Does type have any aliases? ISymbol alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayService = document.GetLanguageService <ISymbolDisplayService>(); var displayText = alias != null ? alias.Name : displayService.ToMinimalDisplayString(semanticModel, position, type); var workspace = document.Project.Solution.Workspace; var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); var item = new CompletionItem( this, displayText: displayText, filterSpan: textChangeSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, alias ?? type), glyph: (alias ?? type).GetGlyph(), preselect: true, rules: ItemRules.Instance); context.AddItem(item); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public ServerCapabilities GetCapabilities(ClientCapabilities clientCapabilities) { var capabilities = new ServerCapabilities(); if (clientCapabilities is VSInternalClientCapabilities vsClientCapabilities && vsClientCapabilities.SupportsVisualStudioExtensions) { capabilities = GetVSServerCapabilities(); } var commitCharacters = CompletionRules.Default.DefaultCommitCharacters.Select(c => c.ToString()).ToArray(); var triggerCharacters = _completionProviders.SelectMany( lz => CommonCompletionUtilities.GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray(); capabilities.DefinitionProvider = true; capabilities.RenameProvider = true; capabilities.ImplementationProvider = true; capabilities.CodeActionProvider = new CodeActionOptions { CodeActionKinds = new[] { CodeActionKind.QuickFix, CodeActionKind.Refactor }, ResolveProvider = true }; capabilities.CompletionProvider = new VisualStudio.LanguageServer.Protocol.CompletionOptions { ResolveProvider = true, AllCommitCharacters = commitCharacters, TriggerCharacters = triggerCharacters, }; capabilities.SignatureHelpProvider = new SignatureHelpOptions { TriggerCharacters = new[] { "(", "," } }; capabilities.DocumentSymbolProvider = true; capabilities.WorkspaceSymbolProvider = true; capabilities.DocumentFormattingProvider = true; capabilities.DocumentRangeFormattingProvider = true; capabilities.DocumentOnTypeFormattingProvider = new DocumentOnTypeFormattingOptions { FirstTriggerCharacter = "}", MoreTriggerCharacter = new[] { ";", "\n" } }; capabilities.ReferencesProvider = true; capabilities.FoldingRangeProvider = true; capabilities.ExecuteCommandProvider = new ExecuteCommandOptions(); capabilities.TextDocumentSync = new TextDocumentSyncOptions { Change = TextDocumentSyncKind.Incremental, OpenClose = true }; capabilities.HoverProvider = true; // Using only range handling has shown to be more performant than using a combination of full/edits/range handling, // especially for larger files. With range handling, we only need to compute tokens for whatever is in view, while // with full/edits handling we need to compute tokens for the entire file and then potentially run a diff between // the old and new tokens. capabilities.SemanticTokensOptions = new SemanticTokensOptions { Full = false, Range = true, Legend = new SemanticTokensLegend { TokenTypes = SemanticTokenTypes.AllTypes.Concat(SemanticTokensHelpers.RoslynCustomTokenTypes).ToArray(), TokenModifiers = new string[] { SemanticTokenModifiers.Static } } }; return(capabilities); }
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.OpenBracketToken && token.Kind() != SyntaxKind.CommaToken) { return(null); } var argumentList = token.Parent as BaseArgumentListSyntax; if (argumentList == null) { return(null); } var semanticModel = await document.GetSemanticModelForNodeAsync(argumentList, cancellationToken).ConfigureAwait(false); var parameterLists = GetParameterLists(semanticModel, position, argumentList.Parent, cancellationToken); if (parameterLists == null) { return(null); } var existingNamedParameters = GetExistingNamedParameters(argumentList, position); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var unspecifiedParameters = parameterLists.SelectMany(pl => pl) .Where(p => !existingNamedParameters.Contains(p.Name)) .Distinct(this); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); return(unspecifiedParameters.Select( p => { // Note: the filter text does not include the ':'. We want to ensure that if // the user types the name exactly (up to the colon) that it is selected as an // exact match. var workspace = document.Project.Solution.Workspace; var escaped = p.Name.ToIdentifierToken().ToString(); return new CompletionItem( this, escaped + ColonString, CompletionUtilities.GetTextChangeSpan(text, position), CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, token.SpanStart, p), p.GetGlyph(), sortText: p.Name, filterText: escaped, rules: ItemRules.Instance); })); }
internal static TextSpan GetTextChangeSpan(SourceText text, int position) { return(CommonCompletionUtilities.GetTextChangeSpan(text, position, IsTextChangeSpanStartCharacter, IsWordCharacter)); }