public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var syntaxContext = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); if (!syntaxContext.IsAwaitKeywordContext(position)) { return; } var method = syntaxContext.TargetToken.GetAncestor(node => node.IsAsyncSupportingFunctionSyntax()); var shouldMakeContainerAsync = method is not null && !method.GetModifiers().Any(SyntaxKind.AsyncKeyword); var completionItem = CommonCompletionItem.Create( displayText: SyntaxFacts.GetText(SyntaxKind.AwaitKeyword), displayTextSuffix: "", rules: CompletionItemRules.Default, Glyph.Keyword, description: RecommendedKeyword.CreateDisplayParts(SyntaxFacts.GetText(SyntaxKind.AwaitKeyword), string.Empty), inlineDescription: shouldMakeContainerAsync ? CSharpFeaturesResources.Make_container_async : null, isComplexTextEdit: shouldMakeContainerAsync); context.AddItem(completionItem); }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { var document = completionContext.Document; var position = completionContext.Position; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var context = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); var index = GetElementIndex(context); if (index == null) { return; } var typeInferrer = document.GetLanguageService <ITypeInferenceService>(); var inferredTypes = typeInferrer.InferTypes(semanticModel, context.TargetToken.Parent.SpanStart, cancellationToken) .Where(t => t.IsTupleType) .Cast <INamedTypeSymbol>() .ToImmutableArray(); AddItems(inferredTypes, index.Value, completionContext); }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { try { var document = completionContext.Document; var position = completionContext.Position; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var workspace = document.Project.Solution.Workspace; var context = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); var index = GetElementIndex(context); if (index == null) { return; } var typeInferrer = document.GetLanguageService <ITypeInferenceService>(); var inferredTypes = typeInferrer.InferTypes(semanticModel, context.TargetToken.Parent.SpanStart, cancellationToken) .Where(t => t.IsTupleType) .Cast <INamedTypeSymbol>() .ToImmutableArray(); AddItems(inferredTypes, index.Value, completionContext, context.TargetToken.Parent.SpanStart); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e)) { // nop } }
public static async Task <SyntaxContext> CreateContextAsync( Document document, int position, bool usePartialSemantic, CancellationToken cancellationToken ) { // Need regular semantic model because we will use it to get imported namespace symbols. Otherwise we will try to // reach outside of the span and ended up with "node not within syntax tree" error from the speculative model. // Also we use partial model unless full model is explictly request (e.g. in tests) so that we don't have to wait for all semantics to be computed. var semanticModel = usePartialSemantic ? await document .GetPartialSemanticModelAsync(cancellationToken) .ConfigureAwait(false) : await document .GetRequiredSemanticModelAsync(cancellationToken) .ConfigureAwait(false); Contract.ThrowIfNull(semanticModel); return(CSharpSyntaxContext.CreateContext( document.Project.Solution.Workspace, semanticModel, position, cancellationToken )); }
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); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var syntaxContext = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); if (syntaxContext.IsInTaskLikeTypeContext) { return; } var token = syntaxContext.TargetToken; if (token.IsMandatoryNamedParameterPosition()) { return; } // Don't show up within member access // This previously worked because the type inferrer didn't work // in member access expressions. // The regular SymbolCompletionProvider will handle completion after . if (token.IsKind(SyntaxKind.DotToken)) { return; } var typeInferenceService = document.GetLanguageService <ITypeInferenceService>(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); var types = typeInferenceService.InferTypes(semanticModel, position, cancellationToken); if (types.Length == 0) { types = ImmutableArray.Create <ITypeSymbol>(semanticModel.Compilation.ObjectType); } foreach (var type in types) { await HandleSingleTypeAsync(context, semanticModel, token, type, cancellationToken).ConfigureAwait(false); } } catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, ErrorSeverity.General)) { throw ExceptionUtilities.Unreachable; } }
protected override async Task <SyntaxContext> CreateContextAsync( Document document, int position, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); return(CSharpSyntaxContext.CreateContext( document.Project.Solution.Workspace, semanticModel, position, cancellationToken)); }
protected override async Task <SyntaxContext> CreateContext(Document document, int position, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); return(CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken)); }
protected override async Task <SyntaxContext> CreateContextAsync(Document document, int position, CancellationToken cancellationToken) { // Need regular semantic model because we will use it to get imported namespace symbols. Otherwise we will try to // reach outside of the span and ended up with "node not within syntax tree" error from the speculative model. var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); return(CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken)); }
public static async Task <SyntaxContext> CreateContextAsync(Document document, int position, CancellationToken cancellationToken) { // Need regular semantic model because we will use it to get imported namespace symbols. Otherwise we will try to // reach outside of the span and ended up with "node not within syntax tree" error from the speculative model. var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(semanticModel); return(CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken)); }
protected override Task <Tuple <ImmutableArray <ISymbol>, SyntaxContext> > GetRecommendedSymbolsAtPositionWorkerAsync( Workspace workspace, SemanticModel semanticModel, int position, OptionSet options, CancellationToken cancellationToken) { var context = CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); var filterOutOfScopeLocals = options.GetOption(RecommendationOptions.FilterOutOfScopeLocals, semanticModel.Language); var symbols = GetSymbolsWorker(context, filterOutOfScopeLocals, cancellationToken); var hideAdvancedMembers = options.GetOption(RecommendationOptions.HideAdvancedMembers, semanticModel.Language); symbols = symbols.FilterToVisibleAndBrowsableSymbols(hideAdvancedMembers, semanticModel.Compilation); return(Task.FromResult(Tuple.Create <ImmutableArray <ISymbol>, SyntaxContext>(symbols, context))); }
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); } }
private void AddKeywords(Workspace workspace, List <CompletionResult> completions, SemanticModel model, int position, bool wantKind, string wordToComplete) { var context = CSharpSyntaxContext.CreateContext(workspace, model, position, CancellationToken.None); var keywordHandler = new KeywordContextHandler(); var keywords = keywordHandler.Get(context, model, position); foreach (var keyword in keywords.Where(k => k.IsValidCompletionFor(wordToComplete))) { completions.Add(new CompletionResult { CompletionText = keyword, DisplayText = keyword, Snippet = keyword, Kind = wantKind ? "Keyword" : null }); } }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { try { var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false); if (!completionContext.Options.GetOption(CompletionOptions.ShowNameSuggestions, LanguageNames.CSharp)) { return; } var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken); if (context.IsInNonUserCode) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false); var baseNames = GetBaseNames(semanticModel, nameInfo); if (baseNames == default) { return; } var recommendedNames = await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, cancellationToken).ConfigureAwait(false); var sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create( CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default); } catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e)) { // nop } }
async void HandleEventHandlerContext() { var analysisDocument = DocumentContext.AnalysisDocument; if (analysisDocument == null) { return; } var partialDoc = analysisDocument.WithFrozenPartialSemantics(default(CancellationToken)); var semanticModel = await partialDoc.GetSemanticModelAsync(default(CancellationToken)); var syntaxContext = CSharpSyntaxContext.CreateContext(DocumentContext.RoslynWorkspace, semanticModel, Editor.CaretOffset, default(CancellationToken)); if (syntaxContext.InferredTypes.Any(t => t.TypeKind == TypeKind.Delegate)) { CompletionWindowManager.HideWindow(); RunCompletionCommand(); } }
public override async Task ProvideCompletionsAsync(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); if (ctx.IsPreProcessorExpressionContext) { var parseOptions = model.SyntaxTree.Options as CSharpParseOptions; foreach (var define in parseOptions.PreprocessorSymbolNames) { context.AddItem(CompletionItem.Create(define)); } } }
private static async Task <bool> ShouldShowSpeculativeTCompletionItemAsync(Document document, int position, CancellationToken cancellationToken) { var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { return(false); } // We could be in the middle of a ref/generic/tuple type, instead of a simple T case. // If we managed to walk out and get a different SpanStart, we treat it as a simple $$T case. var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); var semanticModel = await document.ReuseExistingSpeculativeModelAsync(token.Parent, cancellationToken).ConfigureAwait(false); var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); if (context.IsInTaskLikeTypeContext) { return(false); } var spanStart = position; while (true) { var oldSpanStart = spanStart; spanStart = WalkOutOfGenericType(syntaxTree, spanStart, semanticModel, cancellationToken); spanStart = WalkOutOfTupleType(syntaxTree, spanStart, cancellationToken); spanStart = WalkOutOfRefType(syntaxTree, spanStart, cancellationToken); if (spanStart == oldSpanStart) { break; } } return(IsStartOfSpeculativeTContext(syntaxTree, spanStart, cancellationToken)); }
public override async Task ProvideCompletionsAsync(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; var enclosingType = model.GetEnclosingNamedType(position, cancellationToken); if (enclosingType == null) { return; } foreach (var type in ctx.InferredTypes) { if (type.TypeKind != TypeKind.Delegate) { continue; } string delegateName = null; if (ctx.TargetToken.IsKind(SyntaxKind.PlusEqualsToken)) { delegateName = GuessEventHandlerBaseName(ctx.TargetToken.Parent, ctx.ContainingTypeDeclaration); } AddDelegateHandlers(context, ctx.TargetToken.Parent, model, type, position, delegateName, cancellationToken); } }
private Task CheckResultAsync(string text, int position, bool absent, CSharpParseOptions options, int?matchPriority) { using var workspace = new TestWorkspace(composition: FeaturesTestCompositions.Features); var solution = workspace.CurrentSolution; var project = solution.AddProject("test", "test", LanguageNames.CSharp); var document = project.AddDocument("test.cs", text); var tree = SyntaxFactory.ParseSyntaxTree(text, options: options); var compilation = CSharpCompilation.Create( "test", syntaxTrees: new[] { tree }, references: new[] { TestMetadata.Net451.mscorlib }); if (tree.IsInNonUserCode(position, CancellationToken.None) && !absent) { Assert.False(true, "Wanted keyword, but in non-user code position: " + keywordText); } var semanticModel = compilation.GetSemanticModel(tree); var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, CancellationToken.None); return(CheckResultAsync(absent, position, context, matchPriority)); }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false); var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken); if (context.IsInNonUserCode) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfo(document, position, cancellationToken).ConfigureAwait(false); if (!IsValidType(nameInfo.Type)) { return; } var type = UnwrapType(nameInfo.Type, semanticModel.Compilation); var baseNames = NameGenerator.GetBaseNames(type); var recommendedNames = await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, cancellationToken).ConfigureAwait(false); int sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create(CSharpFeaturesResources.Name, CompletionItemRules.Default); }
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; } }
protected override Task <SyntaxContext> CreateContextAsync(Workspace workspace, SemanticModel semanticModel, int position, CancellationToken cancellationToken) => Task.FromResult <SyntaxContext>(CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken));
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)); } } } }
protected override Task <SyntaxContext> CreateSyntaxContextAsync(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken) { return(Task.FromResult <SyntaxContext>(CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken))); }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { try { var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); if (!completionContext.CompletionOptions.ShowNameSuggestions) { return; } var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); if (context.IsInNonUserCode) { return; } var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false); using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result); // Suggest names from existing overloads. if (nameInfo.PossibleSymbolKinds.Any(k => k.SymbolKind == SymbolKind.Parameter)) { var(_, partialSemanticModel) = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (partialSemanticModel is not null) { AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken); } } var baseNames = GetBaseNames(semanticModel, nameInfo); if (baseNames != default) { await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, result, cancellationToken).ConfigureAwait(false); } var recommendedNames = result.ToImmutable(); if (recommendedNames.IsEmpty) { return; } var sortValue = 0; foreach (var(name, kind) in recommendedNames) { // We've produced items in the desired order, add a sort text to each item to prevent alphabetization completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8"))); sortValue++; } completionContext.SuggestionModeItem = CommonCompletionItem.Create( CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General)) { // nop } }
private static async Task <ImmutableArray <CompletionItem> > GetSnippetsForDocumentAsync( Document document, int position, CancellationToken cancellationToken) { var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var semanticFacts = document.GetRequiredLanguageService <ISemanticFactsService>(); var root = syntaxTree.GetRoot(cancellationToken); var leftToken = root.FindTokenOnLeftOfPosition(position, includeDirectives: true); var targetToken = leftToken.GetPreviousTokenIfTouchingWord(position); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken) || syntaxFacts.GetContainingTypeDeclaration(root, position) is EnumDeclarationSyntax || syntaxTree.IsPossibleTupleContext(leftToken, position)) { return(ImmutableArray <CompletionItem> .Empty); } var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); if (context.IsInTaskLikeTypeContext) { return(ImmutableArray <CompletionItem> .Empty); } if (syntaxFacts.IsPreProcessorDirectiveContext(syntaxTree, position, cancellationToken)) { var directive = leftToken.GetAncestor <DirectiveTriviaSyntax>(); Contract.ThrowIfNull(directive); if (!directive.DirectiveNameToken.IsKind( SyntaxKind.IfKeyword, SyntaxKind.RegionKeyword, SyntaxKind.ElseKeyword, SyntaxKind.ElifKeyword, SyntaxKind.ErrorKeyword, SyntaxKind.LineKeyword, SyntaxKind.PragmaKeyword, SyntaxKind.EndIfKeyword, SyntaxKind.UndefKeyword, SyntaxKind.EndRegionKeyword, SyntaxKind.WarningKeyword)) { return(GetSnippetCompletionItems( document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: true)); } } else { if (semanticFacts.IsGlobalStatementContext(semanticModel, position, cancellationToken) || semanticFacts.IsExpressionContext(semanticModel, position, cancellationToken) || semanticFacts.IsStatementContext(semanticModel, position, cancellationToken) || semanticFacts.IsTypeContext(semanticModel, position, cancellationToken) || semanticFacts.IsTypeDeclarationContext(semanticModel, position, cancellationToken) || semanticFacts.IsNamespaceContext(semanticModel, position, cancellationToken) || semanticFacts.IsNamespaceDeclarationNameContext(semanticModel, position, cancellationToken) || semanticFacts.IsMemberDeclarationContext(semanticModel, position, cancellationToken) || semanticFacts.IsLabelContext(semanticModel, position, cancellationToken)) { return(GetSnippetCompletionItems( document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: false)); } } return(ImmutableArray <CompletionItem> .Empty); }
public override async Task ProduceCompletionListAsync(CompletionListContext 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) .Where(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); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); foreach (var member in members) { var displayText = member.ToMinimalDisplayString(semanticModel, namePosition, s_signatureDisplayFormat); var insertionText = displayText; context.AddItem(new SymbolCompletionItem( this, displayText, insertionText: insertionText, filterSpan: textChangeSpan, position: position, symbols: new List <ISymbol> { member }, context: CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken), rules: ItemRules.Instance)); } }
async Task <ICompletionDataList> InternalHandleCodeCompletion(CodeCompletionContext completionContext, CompletionTriggerInfo triggerInfo, int triggerWordLength, CancellationToken token, bool forceSymbolCompletion = false) { var analysisDocument = DocumentContext.AnalysisDocument; if (analysisDocument == null) { return(EmptyCompletionDataList); } var cs = DocumentContext.RoslynWorkspace.Services.GetLanguageServices(LanguageNames.CSharp).GetService <CompletionService> (); SourceText sourceText; if (!analysisDocument.TryGetText(out sourceText)) { return(EmptyCompletionDataList); } CompletionTriggerKind kind; switch (triggerInfo.CompletionTriggerReason) { case CompletionTriggerReason.CharTyped: kind = CompletionTriggerKind.Insertion; if (triggerInfo.TriggerCharacter == '{') { return(EmptyCompletionDataList); } break; case CompletionTriggerReason.CompletionCommand: kind = CompletionTriggerKind.InvokeAndCommitIfUnique; break; case CompletionTriggerReason.BackspaceOrDeleteCommand: kind = CompletionTriggerKind.Deletion; break; case CompletionTriggerReason.RetriggerCommand: kind = CompletionTriggerKind.InvokeAndCommitIfUnique; break; default: kind = CompletionTriggerKind.Insertion; break; } var triggerSnapshot = Editor.GetPlatformTextBuffer().CurrentSnapshot; var trigger = new CompletionTrigger(kind, triggerInfo.TriggerCharacter.HasValue ? triggerInfo.TriggerCharacter.Value : '\0'); if (triggerInfo.CompletionTriggerReason == CompletionTriggerReason.CharTyped) { if (!cs.ShouldTriggerCompletion(sourceText, completionContext.TriggerOffset, trigger, null)) { return(EmptyCompletionDataList); } } completionContext.Trace("C#: Getting completions"); var customOptions = DocumentContext.RoslynWorkspace.Options .WithChangedOption(CompletionOptions.TriggerOnDeletion, LanguageNames.CSharp, true) .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, IdeApp.Preferences.CompletionOptionsHideAdvancedMembers) // Roslyn's implementation of this feature doesn't work correctly in old editor .WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, false); var completionList = await Task.Run(() => cs.GetCompletionsAsync(analysisDocument, Editor.CaretOffset, trigger, options: customOptions, cancellationToken: token)).ConfigureAwait(false); completionContext.Trace("C#: Got completions"); if (completionList == null) { return(EmptyCompletionDataList); } var result = new CompletionDataList(); result.TriggerWordLength = triggerWordLength; CSharpCompletionData defaultCompletionData = null; bool first = true, addProtocolCompletion = false; foreach (var item in completionList.Items) { if (string.IsNullOrEmpty(item.DisplayText)) { continue; } var data = new CSharpCompletionData(analysisDocument, triggerSnapshot, cs, item); if (first) { first = false; addProtocolCompletion = data.Provider is OverrideCompletionProvider; } result.Add(data); if (item.Rules.MatchPriority > 0) { if (defaultCompletionData == null || defaultCompletionData.Rules.MatchPriority < item.Rules.MatchPriority) { defaultCompletionData = data; } } } result.AutoCompleteUniqueMatch = (triggerInfo.CompletionTriggerReason == CompletionTriggerReason.CompletionCommand); var partialDoc = analysisDocument.WithFrozenPartialSemantics(token); var semanticModel = await partialDoc.GetSemanticModelAsync(token).ConfigureAwait(false); var syntaxContext = CSharpSyntaxContext.CreateContext(DocumentContext.RoslynWorkspace, semanticModel, completionContext.TriggerOffset, token); if (forceSymbolCompletion || IdeApp.Preferences.AddImportedItemsToCompletionList) { completionContext.Trace("C#: Adding import completion data"); AddImportCompletionData(syntaxContext, result, semanticModel, completionContext.TriggerOffset, token); completionContext.Trace("C#: Added import completion data"); } if (defaultCompletionData != null) { result.DefaultCompletionString = defaultCompletionData.DisplayText; } if (completionList.SuggestionModeItem != null) { if (completionList.Items.Contains(completionList.SuggestionModeItem)) { result.DefaultCompletionString = completionList.SuggestionModeItem.DisplayText; } // if a suggestion mode item is present autoselection is disabled // for example in the lambda case the suggestion mode item is '<lambda expression>' which is not part of the completion item list but taggs the completion list as auto select == false. result.AutoSelect = false; } if (triggerInfo.TriggerCharacter == '_' && triggerWordLength == 1) { result.AutoSelect = false; } if (triggerInfo.TriggerCharacter == ' ') { result.AutoCompleteEmptyMatch = true; } return(result); }
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 async Task <IEnumerable <CompletionItem> > GetCompletionsOffOfExplicitInterfaceAsync( Document document, SemanticModel semanticModel, int position, NameSyntax name, CancellationToken cancellationToken) { // Bind the interface name which is to the left of the dot var syntaxTree = semanticModel.SyntaxTree; var nameBinding = semanticModel.GetSymbolInfo(name, cancellationToken); var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken); var symbol = nameBinding.Symbol as ITypeSymbol; if (symbol == null || symbol.TypeKind != TypeKind.Interface) { return(SpecializedCollections.EmptyEnumerable <CompletionItem>()); } var members = semanticModel.LookupSymbols( position: name.SpanStart, container: symbol) .Where(s => !s.IsStatic) .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation); // We're going to create a entry for each one, including the signature var completions = new List <CompletionItem>(); var signatureDisplayFormat = new SymbolDisplayFormat( genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, memberOptions: SymbolDisplayMemberOptions.IncludeParameters, parameterOptions: SymbolDisplayParameterOptions.IncludeName | SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeParamsRefOut, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); var namePosition = name.SpanStart; var text = await context.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, context.Position); foreach (var member in members) { var displayString = member.ToMinimalDisplayString(semanticModel, namePosition, signatureDisplayFormat); var memberCopied = member; var insertionText = displayString; completions.Add(new SymbolCompletionItem( this, displayString, insertionText: insertionText, filterSpan: textChangeSpan, position: position, symbols: new List <ISymbol> { member }, context: context, rules: ItemRules.Instance)); } return(completions); }