public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; using (Logger.LogBlock(FunctionId.Completion_SnippetCompletionProvider_GetItemsWorker_CSharp, cancellationToken)) { // TODO (https://github.com/dotnet/roslyn/issues/5107): Enable in Interactive. var workspace = document.Project.Solution.Workspace; if (!workspace.CanApplyChange(ApplyChangesKind.ChangeDocument) || workspace.Kind == WorkspaceKind.Debugger || workspace.Kind == WorkspaceKind.Interactive) { return; } var snippetCompletionItems = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( UnionCompletionItemComparer.Instance, (d, c) => GetSnippetsForDocumentAsync(d, position, context.DefaultItemSpan, workspace, c), cancellationToken).ConfigureAwait(false); context.AddItems(snippetCompletionItems); } }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var ctx = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); if (ctx.TargetToken.Parent != null && ctx.TargetToken.Parent.Parent != null && ctx.TargetToken.Parent.Parent.IsKind(SyntaxKind.Argument)) { SourceText text; if (!context.Document.TryGetText(out text)) { text = await context.Document.GetTextAsync(); } var currentChar = text [context.Position - 1]; if (ctx.TargetToken.Parent == null || !ctx.TargetToken.Parent.IsKind(SyntaxKind.StringLiteralExpression) || ctx.TargetToken.Parent.Parent == null || !ctx.TargetToken.Parent.Parent.IsKind(SyntaxKind.Argument) || ctx.TargetToken.Parent.Parent.Parent == null || !ctx.TargetToken.Parent.Parent.Parent.IsKind(SyntaxKind.ArgumentList) || ctx.TargetToken.Parent.Parent.Parent.Parent == null || !ctx.TargetToken.Parent.Parent.Parent.Parent.IsKind(SyntaxKind.InvocationExpression)) { return; } var formatArgument = GetFormatItemNumber(document, position); var invocationExpression = ctx.TargetToken.Parent.Parent.Parent.Parent as InvocationExpressionSyntax; GetFormatCompletionData(context, semanticModel, invocationExpression, formatArgument, currentChar); } }
void GetFormatCompletionForType(Microsoft.CodeAnalysis.Completion.CompletionContext completionContext, ITypeSymbol type) { if (type == null) { GenerateNumberFormatitems(completionContext); GenerateDateTimeFormatitems(completionContext); GenerateTimeSpanFormatitems(completionContext); GenerateEnumFormatitems(completionContext); GenerateGuidFormatitems(completionContext); return; } switch (type.ToString()) { case "long": case "System.Int64": case "ulong": case "System.UInt64": case "int": case "System.Int32": case "uint": case "System.UInt32": case "short": case "System.Int16": case "ushort": case "System.UInt16": case "byte": case "System.Byte": case "sbyte": case "System.SByte": GenerateNumberFormatitems(completionContext); break; case "float": case "System.Single": case "double": case "System.Double": case "decimal": case "System.Decimal": GenerateNumberFormatitems(completionContext); break; case "System.Enum": GenerateEnumFormatitems(completionContext); break; case "System.DateTime": GenerateDateTimeFormatitems(completionContext); break; case "System.TimeSpan": GenerateTimeSpanFormatitems(completionContext); break; case "System.Guid": GenerateGuidFormatitems(completionContext); break; } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return; } var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (!token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.CommaToken)) { return; } var attributeArgumentList = token.Parent as AttributeArgumentListSyntax; var attributeSyntax = token.Parent.Parent as AttributeSyntax; if (attributeSyntax == null || attributeArgumentList == null) { return; } if (IsAfterNameColonArgument(token) || IsAfterNameEqualsArgument(token)) { context.IsExclusive = true; } // 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(context, semanticModel, token, attributeSyntax, existingNamedParameters).ConfigureAwait(false); var nameEqualsItems = await GetNameEqualsItemsAsync(context, semanticModel, token, attributeSyntax, existingNamedParameters).ConfigureAwait(false); context.AddItems(nameEqualsItems); // If we're after a name= parameter, then we only want to show name= parameters. // Otherwise, show name: parameters too. if (!IsAfterNameEqualsArgument(token)) { context.AddItems(nameColonItems); } }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var ctx = CSharpSyntaxContext.CreateContext(workspace, model, position, cancellationToken); var syntaxTree = ctx.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { return; } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon( position, syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken).GetPreviousTokenIfTouchingWord(position), cancellationToken)) { return; } var ma = ctx.LeftToken.Parent as MemberAccessExpressionSyntax; if (ma == null) { return; } var symbolInfo = model.GetSymbolInfo(ma.Expression); if (symbolInfo.Symbol == null || symbolInfo.Symbol.Kind != SymbolKind.Parameter) { return; } var within = model.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); var addedSymbols = new HashSet <string> (); foreach (var ano in ma.AncestorsAndSelf().OfType <AnonymousMethodExpressionSyntax> ()) { Analyze(context, model, ma.Expression, within, ano.ParameterList, symbolInfo.Symbol, addedSymbols, cancellationToken); } foreach (var ano in ma.AncestorsAndSelf().OfType <ParenthesizedLambdaExpressionSyntax> ()) { Analyze(context, model, ma.Expression, within, ano.ParameterList, symbolInfo.Symbol, addedSymbols, cancellationToken); } }
void Analyze(Microsoft.CodeAnalysis.Completion.CompletionContext context, SemanticModel model, SyntaxNode node, ITypeSymbol type, ITypeSymbol stopAt, ISymbol within, HashSet <string> addedSymbols, CancellationToken cancellationToken) { var startType = type; var typeString = CSharpAmbience.SafeMinimalDisplayString(type, model, context.CompletionListSpan.Start, Ambience.LabelFormat); var pDict = ImmutableDictionary <string, string> .Empty; if (typeString != null) { pDict = pDict.Add("CastTypeString", typeString); } pDict = pDict.Add("DescriptionMarkup", "- <span foreground=\"darkgray\" size='small'>" + GettextCatalog.GetString("Cast to '{0}'", type.Name) + "</span>"); pDict = pDict.Add("NodeString", node.ToString()); while (type != null && type.SpecialType != SpecialType.System_Object && type != stopAt) { foreach (var member in type.GetMembers()) { cancellationToken.ThrowIfCancellationRequested(); if (member.IsImplicitlyDeclared || member.IsStatic) { continue; } if (member.IsOrdinaryMethod() || member.Kind == SymbolKind.Field || member.Kind == SymbolKind.Property) { if (member.IsAccessibleWithin(within)) { var completionData = SymbolCompletionItem.CreateWithSymbolId( member.Name, new [] { member }, CompletionItemRules.Default, context.Position, properties: pDict ); if (addedSymbols.Contains(completionData.DisplayText)) { continue; } addedSymbols.Add(completionData.DisplayText); context.AddItem(completionData); } } } type = type.BaseType; } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { 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.IsEntirelyWithinCrefSyntax(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDocumentationComments: true) .GetPreviousTokenIfTouchingWord(position); // To get a Speculative SemanticModel (which is much faster), we need to // walk up to the node the DocumentationTrivia is attached to. var parentNode = token.Parent.FirstAncestorOrSelf<DocumentationCommentTriviaSyntax>()?.ParentTrivia.Token.Parent; _testSpeculativeNodeCallbackOpt?.Invoke(parentNode); if (parentNode == null) { return; } var semanticModel = await document.GetSemanticModelForNodeAsync( parentNode, cancellationToken).ConfigureAwait(false); var symbols = GetSymbols(token, semanticModel, cancellationToken); symbols = symbols.FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation); if (!symbols.Any()) { return; } context.IsExclusive = true; var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var span = GetCompletionItemSpan(text, position); var items = CreateCompletionItems(document.Project.Solution.Workspace, semanticModel, symbols, token, span); context.AddItems(items); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var showSpeculativeT = await document.IsValidContextForDocumentOrLinkedDocumentsAsync( (doc, ct) => ShouldShowSpeculativeTCompletionItemAsync(doc, position, ct), cancellationToken).ConfigureAwait(false); if (showSpeculativeT) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); const string T = nameof(T); context.AddItem(CommonCompletionItem.Create(T, glyph: Glyph.TypeParameter)); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var targetToken = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (targetToken.IsKind(SyntaxKind.AliasKeyword) && targetToken.Parent.IsKind(SyntaxKind.ExternAliasDirective)) { var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var aliases = compilation.ExternalReferences.SelectMany(r => r.Properties.Aliases).ToSet(); if (aliases.Any()) { var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var usedAliases = root.ChildNodes().OfType<ExternAliasDirectiveSyntax>() .Where(e => !e.Identifier.IsMissing) .Select(e => e.Identifier.ValueText); aliases.RemoveRange(usedAliases); aliases.Remove(MetadataReferenceProperties.GlobalAlias); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); foreach (var alias in aliases) { context.AddItem(CommonCompletionItem.Create(alias, glyph: Glyph.Namespace)); } } } }
void GetFormatCompletionData(Microsoft.CodeAnalysis.Completion.CompletionContext engine, SemanticModel semanticModel, InvocationExpressionSyntax invocationExpression, int formatArgument, char currentChar) { var symbolInfo = semanticModel.GetSymbolInfo(invocationExpression); var method = symbolInfo.Symbol as IMethodSymbol ?? symbolInfo.CandidateSymbols.OfType <IMethodSymbol> ().FirstOrDefault(); var ma = invocationExpression.Expression as MemberAccessExpressionSyntax; if (ma != null && ma.Name.ToString() == "ToString") { if (method == null || currentChar != '"') { return; } if (method != null) { GetFormatCompletionForType(engine, method.ContainingType); } return; } else { if (method == null || currentChar != ':') { return; } ExpressionSyntax fmtArgumets; IList <ExpressionSyntax> args; if (FormatStringHelper.TryGetFormattingParameters(semanticModel, invocationExpression, out fmtArgumets, out args, null)) { ITypeSymbol type = null; if (formatArgument + 1 < args.Count) { var invokeArgument = semanticModel.GetSymbolInfo(args [formatArgument + 1]); if (invokeArgument.Symbol != null) { type = invokeArgument.Symbol.GetReturnType(); } } GetFormatCompletionForType(engine, type); } } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; // the provider might be invoked in non-interactive context: Workspace ws; SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (Workspace.TryGetWorkspace(sourceText.Container, out ws)) { var workspace = ws as InteractiveWorkspace; if (workspace != null) { var window = workspace.Window; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (await ShouldDisplayCommandCompletionsAsync(tree, position, cancellationToken).ConfigureAwait(false)) { IInteractiveWindowCommands commands = window.GetInteractiveCommands(); if (commands != null) { foreach (var command in commands.GetCommands()) { foreach (var commandName in command.Names) { string completion = GetCompletionString(commandName); context.AddItem(CommonCompletionItem.Create( completion, description: command.Description.ToSymbolDisplayParts(), glyph: Glyph.Intrinsic)); } } } } } } }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var ctx = CSharpSyntaxContext.CreateContext(workspace, model, position, cancellationToken); var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(context.Position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(context.Position, cancellationToken); if (token.IsKind(SyntaxKind.DotToken) || token.IsMandatoryNamedParameterPosition()) { return; } // check if it's the first parameter and set autoselect == false if a parameterless version exists. if (token.IsKind(SyntaxKind.OpenParenToken)) { var parent = token.Parent?.Parent; if (parent == null) { return; } var symbolInfo = model.GetSymbolInfo(parent); foreach (var symbol in new [] { symbolInfo.Symbol }.Concat(symbolInfo.CandidateSymbols)) { if (symbol != null && symbol.IsKind(SymbolKind.Method)) { if (symbol.GetParameters().Length == 0) { // completionResult.AutoSelect = false; break; } } } } foreach (var _type in ctx.InferredTypes) { var type = _type; if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { continue; } } if (type.TypeKind != TypeKind.Enum) { continue; } if (!type.IsEditorBrowsable()) { continue; } // Does type have any aliases? ISymbol alias = await type.FindApplicableAlias(context.Position, model, cancellationToken).ConfigureAwait(false); if (!IsReachable(model, type, token.Parent)) { var pDict = ImmutableDictionary <string, string> .Empty; var displayString = CSharpAmbience.SafeMinimalDisplayString(type, model, context.Position, SymbolDisplayFormat.CSharpErrorMessageFormat); var item = CompletionItem.Create(displayString, properties: pDict, tags: tags); context.AddItem(item.WithRules(item.Rules.WithMatchPriority(int.MaxValue))); } foreach (IFieldSymbol field in type.GetMembers().OfType <IFieldSymbol> ()) { if (field.DeclaredAccessibility == Accessibility.Public && (field.IsConst || field.IsStatic)) { var displayString = CSharpAmbience.SafeMinimalDisplayString(alias ?? field.Type, model, context.Position, SymbolDisplayFormat.CSharpErrorMessageFormat) + "." + field.Name; var pDict = ImmutableDictionary <string, string> .Empty; context.AddItem(CompletionItem.Create(displayString, properties: pDict, tags: tags)); } } } }
/// <summary> /// Implement to contribute <see cref="CompletionItem"/>'s and other details to a <see cref="CompletionList"/> /// </summary> public abstract Task ProvideCompletionsAsync(CompletionContext context);
private static bool HasAnyItems(CompletionContext cc) { return(cc.Items.Count > 0 || cc.SuggestionModeItem != null); }
void GenerateGuidFormatitems(Microsoft.CodeAnalysis.Completion.CompletionContext completionContext) { completionContext.AddItems(guidFormatItems); }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var ctx = CSharpSyntaxContext.CreateContext(workspace, model, position, cancellationToken); var syntaxTree = ctx.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { return; } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon( position, syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken).GetPreviousTokenIfTouchingWord(position), cancellationToken)) { return; } var ma = ctx.LeftToken.Parent as MemberAccessExpressionSyntax; if (ma == null) { return; } var symbolInfo = model.GetSymbolInfo(ma.Expression); if (symbolInfo.Symbol == null) { return; } var within = model.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); var addedSymbols = new HashSet <string> (); SyntaxNode ancestor = ma.Expression; while (ancestor != null) { // check parent if for direct type check var ifStmSyntax = ancestor as IfStatementSyntax; if (ifStmSyntax != null) { var condition = SkipParens(ifStmSyntax.Condition); if (condition != null && condition.IsKind(SyntaxKind.IsExpression)) { var isExpr = ((BinaryExpressionSyntax)condition); var leftSymbol = model.GetSymbolInfo(isExpr.Left); if (leftSymbol.Symbol == symbolInfo.Symbol) { var type = model.GetTypeInfo(isExpr.Right).Type; if (type != null) { Analyze(context, model, ma.Expression, type, model.GetTypeInfo(isExpr.Left).Type, within, addedSymbols, cancellationToken); } } } // skip if else ... if else if (ancestor.Parent is ElseClauseSyntax) { while (ancestor is IfStatementSyntax || ancestor is ElseClauseSyntax) { ancestor = ancestor.Parent; } continue; } goto loop; } // check parent block if an if is there that checks the type var blockSyntax = ancestor as BlockSyntax; if (blockSyntax != null) { foreach (var ifStmt in blockSyntax.Statements.OfType <IfStatementSyntax> ()) { if (ifStmt.Span.End >= ma.Span.Start) { break; } var condition = SkipParens(ifStmt.Condition); bool wasNegated = false; if (condition.IsKind(SyntaxKind.LogicalNotExpression)) { condition = SkipParens(((PrefixUnaryExpressionSyntax)condition).Operand); wasNegated = true; } if (condition == null || !condition.IsKind(SyntaxKind.IsExpression)) { goto loop; } var stmt = ifStmt.Statement; if (stmt is BlockSyntax) { stmt = ((BlockSyntax)stmt).Statements.LastOrDefault(); } if (!wasNegated || stmt == null || !stmt.IsKind(SyntaxKind.ReturnStatement) && !stmt.IsKind(SyntaxKind.ContinueStatement) && !stmt.IsKind(SyntaxKind.BreakStatement) && !stmt.IsKind(SyntaxKind.ThrowStatement)) { goto loop; } var isExpr = ((BinaryExpressionSyntax)condition); var leftSymbol = model.GetSymbolInfo(isExpr.Left); if (leftSymbol.Symbol == symbolInfo.Symbol) { var type = model.GetTypeInfo(isExpr.Right).Type; if (type != null) { Analyze(context, model, ma.Expression, type, model.GetTypeInfo(isExpr.Left).Type, within, addedSymbols, cancellationToken); } } } } var binOp = ancestor as BinaryExpressionSyntax; if (binOp != null && binOp.IsKind(SyntaxKind.LogicalAndExpression)) { if (SkipParens(binOp.Left).IsKind(SyntaxKind.IsExpression)) { var isExpr = (BinaryExpressionSyntax)SkipParens(binOp.Left); var leftSymbol = model.GetSymbolInfo(isExpr.Left); if (leftSymbol.Symbol == symbolInfo.Symbol) { var type = model.GetTypeInfo(isExpr.Right).Type; if (type != null) { Analyze(context, model, ma.Expression, type, model.GetTypeInfo(isExpr.Left).Type, within, addedSymbols, cancellationToken); } } } } loop : ancestor = ancestor.Parent; } }
private async Task<IEnumerable<CompletionItem>> GetNameColonItemsAsync( CompletionContext context, SemanticModel semanticModel, SyntaxToken token, AttributeSyntax attributeSyntax, ISet<string> existingNamedParameters) { var parameterLists = GetParameterLists(semanticModel, context.Position, attributeSyntax, context.CancellationToken); parameterLists = parameterLists.Where(pl => IsValid(pl, existingNamedParameters)); var text = await semanticModel.SyntaxTree.GetTextAsync(context.CancellationToken).ConfigureAwait(false); return from pl in parameterLists from p in pl where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.Create( displayText: p.Name.ToIdentifierToken().ToString() + ColonString, insertionText: null, symbol: p, contextPosition: token.SpanStart, sortText: p.Name, rules: CompletionItemRules.Default); }
void GenerateTimeSpanFormatitems(Microsoft.CodeAnalysis.Completion.CompletionContext completionContext) { completionContext.AddItems(timeSpanFormatItems); }
void AddFormatCompletionData(Microsoft.CodeAnalysis.Completion.CompletionContext context, bool isVerbatimString) { context.AddItems(isVerbatimString ? verbatimFormatItems : formatItems); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var span = new TextSpan(position, length: 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); var semanticFacts = document.GetLanguageService<ISemanticFactsService>(); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || semanticFacts.IsPreProcessorDirectiveContext(semanticModel, position, cancellationToken)) { return; } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) { return; } var node = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position) .Parent; if (node.Kind() != SyntaxKind.ExplicitInterfaceSpecifier) { return; } // Bind the interface name which is to the left of the dot var name = ((ExplicitInterfaceSpecifierSyntax)node).Name; var symbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol as ITypeSymbol; if (symbol?.TypeKind != TypeKind.Interface) { return; } var members = semanticModel.LookupSymbols( position: name.SpanStart, container: symbol) .WhereAsArray(s => !s.IsStatic) .FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation); // We're going to create a entry for each one, including the signature var namePosition = name.SpanStart; var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); foreach (var member in members) { var displayText = member.ToMinimalDisplayString( semanticModel, namePosition, s_signatureDisplayFormat); var insertionText = displayText; var item = SymbolCompletionItem.Create( displayText, insertionText: insertionText, symbol: member, contextPosition: position, rules: CompletionItemRules.Default); item = item.AddProperty(InsertionTextOnOpenParen, member.Name); context.AddItem(item); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var text = await context.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var items = GetItems(text, context.Document, context.Position, context.Trigger, context.CancellationToken); context.AddItems(items); }
public override async Task ProvideCompletionsAsync(CompletionContext 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>(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); 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 item = SymbolCompletionItem.Create( displayText: displayText, insertionText: null, span: context.DefaultItemSpan, symbol: alias ?? type, descriptionPosition: position, matchPriority: MatchPriority.Preselect, rules: s_rules); context.AddItem(item); } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var ctx = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); if (context.Trigger.Character == '\\') { if (ctx.TargetToken.Parent != null && ctx.TargetToken.Parent.Parent != null && ctx.TargetToken.Parent.Parent.IsKind(SyntaxKind.Argument)) { var argument = ctx.TargetToken.Parent.Parent as ArgumentSyntax; var symbolInfo = semanticModel.GetSymbolInfo(ctx.TargetToken.Parent.Parent.Parent.Parent); if (symbolInfo.Symbol == null) { return; } if (SemanticHighlightingVisitor <string> .IsRegexMatchMethod(symbolInfo)) { if (((ArgumentListSyntax)argument.Parent).Arguments [1] != argument) { return; } AddFormatCompletionData(context, argument.Expression.ToString() [0] == '@'); return; } if (SemanticHighlightingVisitor <string> .IsRegexConstructor(symbolInfo)) { if (((ArgumentListSyntax)argument.Parent).Arguments [0] != argument) { return; } AddFormatCompletionData(context, argument.Expression.ToString() [0] == '@'); return; } } } else { var ma = ctx.TargetToken.Parent as MemberAccessExpressionSyntax; if (ma != null) { var symbolInfo = semanticModel.GetSymbolInfo(ma.Expression); var typeInfo = semanticModel.GetTypeInfo(ma.Expression); var type = typeInfo.Type; if (type != null && type.Name == "Match" && type.ContainingNamespace.GetFullName() == "System.Text.RegularExpressions") { foreach (var grp in GetGroups(ctx, symbolInfo.Symbol)) { context.AddItem(FormatItemCompletionProvider.CreateCompletionItem("Groups[\"" + grp + "\"]", null, null)); } } } } }
private static async Task<CompletionContext> GetProviderCompletionsAsync( CompletionProvider provider, Document document, int position, TextSpan defaultFilterSpan, CompletionTrigger triggerInfo, OptionSet options, CancellationToken cancellationToken) { var context = new CompletionContext(provider, document, position, defaultFilterSpan, triggerInfo, options, cancellationToken); await provider.ProvideCompletionsAsync(context).ConfigureAwait(false); return context; }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var tree = model.SyntaxTree; if (tree.IsInNonUserCode(context.Position, cancellationToken)) { return; } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var startLineNumber = text.Lines.IndexOf(context.Position); // modifiers* override modifiers* type? | //DeclarationModifiers modifiers; var token = tree.FindTokenOnLeftOfPosition(context.Position, cancellationToken); if (token.Parent == null) { return; } // don't show up in that case: int { $$ if (token.Parent.IsKind(SyntaxKind.SkippedTokensTrivia)) { return; } var im = token.Parent.Ancestors().OfType <IncompleteMemberSyntax> ().FirstOrDefault(); if (im != null) { var token2 = tree.FindTokenOnLeftOfPosition(im.Span.Start, cancellationToken); if (token2.Parent.IsKind(SyntaxKind.SkippedTokensTrivia)) { return; } } var parentMember = token.Parent.AncestorsAndSelf().OfType <MemberDeclarationSyntax> ().FirstOrDefault(m => !m.IsKind(SyntaxKind.IncompleteMember)); if (!(parentMember is BaseTypeDeclarationSyntax) && /* May happen in case: * * override $ * public override string Foo () {} */ !(token.IsKind(SyntaxKind.OverrideKeyword) && token.Span.Start <= parentMember.Span.Start)) { return; } var startToken = token.GetPreviousTokenIfTouchingWord(position); TryDetermineReturnType(startToken, model, cancellationToken, out ITypeSymbol returnType, out SyntaxToken tokenBeforeReturnType); if (returnType == null) { var enclosingType = model.GetEnclosingSymbol(position, cancellationToken) as INamedTypeSymbol; if (enclosingType != null && (startToken.IsKind(SyntaxKind.OpenBraceToken) || startToken.IsKind(SyntaxKind.CloseBraceToken) || startToken.IsKind(SyntaxKind.SemicolonToken))) { CreateCompletionData(context, model, position, returnType, Accessibility.NotApplicable, startToken, tokenBeforeReturnType, false, cancellationToken); return; } } if (!TryDetermineModifiers(ref tokenBeforeReturnType, text, startLineNumber, out Accessibility seenAccessibility /*, out modifiers*/) || !TryCheckForTrailingTokens(tree, text, startLineNumber, position, cancellationToken)) { return; } CreateCompletionData(context, model, position, returnType, seenAccessibility, startToken, tokenBeforeReturnType, true, cancellationToken); } catch (OperationCanceledException) { return; } }
public override async Task ProvideCompletionsAsync(Microsoft.CodeAnalysis.Completion.CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelForSpanAsync(new TextSpan (position, 0), cancellationToken).ConfigureAwait(false); var tree = model.SyntaxTree; if (tree.IsInNonUserCode(context.Position, cancellationToken)) { return; } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var startLineNumber = text.Lines.IndexOf(context.Position); // modifiers* override modifiers* type? | //DeclarationModifiers modifiers; var token = tree.FindTokenOnLeftOfPosition(context.Position, cancellationToken); if (token.Parent == null) { return; } // don't show up in that case: int { $$ if (token.Parent.IsKind(SyntaxKind.SkippedTokensTrivia)) { return; } var im = token.Parent.Ancestors().OfType <IncompleteMemberSyntax> ().FirstOrDefault(); if (im != null) { var token2 = tree.FindTokenOnLeftOfPosition(im.Span.Start, cancellationToken); if (token2.Parent.IsKind(SyntaxKind.SkippedTokensTrivia)) { return; } } var parentMember = token.Parent.AncestorsAndSelf().OfType <MemberDeclarationSyntax> ().FirstOrDefault(m => !m.IsKind(SyntaxKind.IncompleteMember)); if (!(parentMember is BaseTypeDeclarationSyntax) && /* May happen in case: * * override $ * public override string Foo () {} */ !(token.IsKind(SyntaxKind.OverrideKeyword) && token.Span.Start <= parentMember.Span.Start)) { return; } var startToken = token.GetPreviousTokenIfTouchingWord(position); // We're marking the context as exclusive, to resolve the // regression in the new editor that appeared since introducing // Roslyn's provider mechanism. The actual override completion // provider took precedence and therefore this one was ignored. // We submitted a PR for roslyn, that allows multiple providers, // marked as exclusive, to render suggestions. // See: https://github.com/dotnet/roslyn/pull/36088 // // Important note, though, we should only set exclusivity when // we are actually competing with an override provider - that // is, if the token before this one is the override keyword. If // it's not, we're not competing, and therefore shouldn't set // this to true, as we'll be the ones stealing the spotlight. context.IsExclusive = startToken.IsKind(SyntaxKind.OverrideKeyword); TryDetermineReturnType(startToken, model, cancellationToken, out ITypeSymbol returnType, out SyntaxToken tokenBeforeReturnType); if (returnType == null) { var enclosingType = model.GetEnclosingSymbol(position, cancellationToken) as INamedTypeSymbol; if (enclosingType != null && (startToken.IsKind(SyntaxKind.OpenBraceToken) || startToken.IsKind(SyntaxKind.CloseBraceToken) || startToken.IsKind(SyntaxKind.SemicolonToken))) { CreateCompletionData(context, model, position, returnType, Accessibility.NotApplicable, startToken, tokenBeforeReturnType, false, cancellationToken); return; } } if (!TryDetermineModifiers(ref tokenBeforeReturnType, text, startLineNumber, out Accessibility seenAccessibility /*, out modifiers*/) || !TryCheckForTrailingTokens(tree, text, startLineNumber, position, cancellationToken)) { return; } CreateCompletionData(context, model, position, returnType, seenAccessibility, startToken, tokenBeforeReturnType, true, cancellationToken); } catch (OperationCanceledException) { return; } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return; } var textChangeSpan = this.GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, itemRules: s_rules); var text = await document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { // Passing null to GetFileSystemDiscoveryService raises an exception. // Instead, return here since there is no longer snapshot for this document. return; } var referenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver; // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolvers. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) ImmutableArray<string> searchPaths; RuntimeMetadataReferenceResolver rtResolver; WorkspaceMetadataFileReferenceResolver workspaceResolver; if ((rtResolver = referenceResolver as RuntimeMetadataReferenceResolver) != null) { searchPaths = rtResolver.PathResolver.SearchPaths; } else if ((workspaceResolver = referenceResolver as WorkspaceMetadataFileReferenceResolver) != null) { searchPaths = workspaceResolver.PathResolver.SearchPaths; } else { return; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, GetFileSystemDiscoveryService(snapshot), Glyph.OpenFolder, Glyph.Assembly, searchPaths: searchPaths, allowableExtensions: new[] { ".dll", ".exe" }, exclude: path => path.Contains(","), itemRules: s_rules); var pathThroughLastSlash = GetPathThroughLastSlash(stringLiteral, position); var documentPath = document.Project.IsSubmission ? null : document.FilePath; context.AddItems(gacHelper.GetItems(pathThroughLastSlash, documentPath)); context.AddItems(fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
private async Task<ImmutableArray<CompletionItem>> GetNameEqualsItemsAsync( CompletionContext context, SemanticModel semanticModel, SyntaxToken token, AttributeSyntax attributeSyntax, ISet<string> existingNamedParameters) { var attributeNamedParameters = GetAttributeNamedParameters(semanticModel, context.Position, attributeSyntax, context.CancellationToken); var unspecifiedNamedParameters = attributeNamedParameters.Where(p => !existingNamedParameters.Contains(p.Name)); var text = await semanticModel.SyntaxTree.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var q = from p in attributeNamedParameters where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.Create( displayText: p.Name.ToIdentifierToken().ToString() + SpaceEqualsString, insertionText: null, symbol: p, contextPosition: token.SpanStart, sortText: p.Name, rules: CompletionItemRules.Default); return q.ToImmutableArray(); }