protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var model = ctx.SemanticModel; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode (completionContext.Position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var token = tree.FindTokenOnLeftOfPosition (completionContext.Position, cancellationToken); if (token.IsMandatoryNamedParameterPosition ()) return Enumerable.Empty<CompletionData> (); var result = new List<CompletionData> (); // 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 Enumerable.Empty<CompletionData> (); 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 (completionContext.Position, model, cancellationToken).ConfigureAwait (false); var displayString = RoslynCompletionData.SafeMinimalDisplayString (type, model, completionContext.Position, SymbolDisplayFormat.CSharpErrorMessageFormat); if (string.IsNullOrEmpty (completionResult.DefaultCompletionString)) { completionResult.DefaultCompletionString = displayString; completionResult.AutoCompleteEmptyMatch = true; } if (!IsReachable (model, type, token.Parent)) result.Add (engine.Factory.CreateSymbolCompletionData (this, type, displayString)); foreach (IFieldSymbol field in type.GetMembers ().OfType<IFieldSymbol> ()) { if (field.DeclaredAccessibility == Accessibility.Public && (field.IsConst || field.IsStatic)) { result.Add (engine.Factory.CreateEnumMemberCompletionData (this, alias, field)); } } } return result; }
protected override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult result, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var tree = ctx.SyntaxTree; var model = ctx.SemanticModel; if (tree.IsInNonUserCode (position, cancellationToken)) return Task.FromResult (Enumerable.Empty<CompletionData> ()); if (!ctx.CSharpSyntaxContext.IsAnyExpressionContext) return Task.FromResult (Enumerable.Empty<CompletionData> ()); var enclosingType = model.GetEnclosingNamedType (position, cancellationToken); var memberMethods = enclosingType.GetMembers ().OfType<IMethodSymbol> ().Where (m => m.MethodKind == MethodKind.Ordinary).ToArray (); var list = new List<CompletionData> (); foreach (var type in ctx.InferredTypes) { if (type.TypeKind != TypeKind.Delegate) continue; AddCompatibleMethods (engine, list, type, memberMethods, cancellationToken); string delegateName = null; if (ctx.TargetToken.IsKind (SyntaxKind.PlusEqualsToken)) { delegateName = GuessEventHandlerBaseName (ctx.LeftToken.Parent, ctx.ContainingTypeDeclaration); } AddDelegateHandlers (list, ctx.TargetToken.Parent, model, engine, result, type, position, delegateName, cancellationToken); } if (list.Count > 0) { result.AutoSelect = false; } return Task.FromResult ((IEnumerable<CompletionData>)list); }
protected override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var position = completionContext.Position; var document = completionContext.Document; var syntaxTree = ctx.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) return Task.FromResult (Enumerable.Empty<CompletionData> ()); if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) return Task.FromResult (Enumerable.Empty<CompletionData> ()); var ma = ctx.LeftToken.Parent as MemberAccessExpressionSyntax; if (ma == null) return Task.FromResult (Enumerable.Empty<CompletionData> ()); var model = ctx.CSharpSyntaxContext.SemanticModel; var symbolInfo = model.GetSymbolInfo (ma.Expression); if (symbolInfo.Symbol == null || symbolInfo.Symbol.Kind != SymbolKind.Parameter) return Task.FromResult (Enumerable.Empty<CompletionData> ()); var list = new List<CompletionData> (); var within = model.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); var addedSymbols = new HashSet<string> (); foreach (var ano in ma.AncestorsAndSelf ().OfType<AnonymousMethodExpressionSyntax> ()) { Analyze (engine, model, ma.Expression, within, list, ano.ParameterList, symbolInfo.Symbol, addedSymbols, cancellationToken); } foreach (var ano in ma.AncestorsAndSelf ().OfType<ParenthesizedLambdaExpressionSyntax> ()) { Analyze (engine, model, ma.Expression, within, list, ano.ParameterList, symbolInfo.Symbol, addedSymbols, cancellationToken); } return Task.FromResult ((IEnumerable<CompletionData>)list); }
/// <summary> /// Given a Symbol, creates the completion item for it. /// </summary> private CompletionItem CreateItem( string displayText, string insertionText, List<ISymbol> symbols, SyntaxContext context, Dictionary<ISymbol, List<ProjectId>> invalidProjectMap, List<ProjectId> totalProjects, bool preselect) { Contract.ThrowIfNull(symbols); SupportedPlatformData supportedPlatformData = null; if (invalidProjectMap != null) { List<ProjectId> invalidProjects = null; foreach (var symbol in symbols) { if (invalidProjectMap.TryGetValue(symbol, out invalidProjects)) { break; } } if (invalidProjects != null) { supportedPlatformData = new SupportedPlatformData(invalidProjects, totalProjects, context.Workspace); } } return CreateItem(displayText, insertionText, symbols, context, preselect, supportedPlatformData); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var position = completionContext.Position; var document = completionContext.Document; var span = new TextSpan(position, 0); var semanticModel = await document.GetCSharpSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; // var ctx = await completionContext.GetSyntaxContextAsync (engine.Workspace, cancellationToken).ConfigureAwait (false); if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { return Enumerable.Empty<CompletionData> (); } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) { return Enumerable.Empty<CompletionData> (); } var node = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position) .Parent; if (node.Kind() == SyntaxKind.ExplicitInterfaceSpecifier) { return await GetCompletionsOffOfExplicitInterfaceAsync( engine, document, semanticModel, position, ((ExplicitInterfaceSpecifierSyntax)node).Name, cancellationToken).ConfigureAwait(false); } return Enumerable.Empty<CompletionData> (); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var tree = ctx.SyntaxTree; //DeclarationModifiers modifiers; SyntaxToken token; var semanticModel = ctx.SemanticModel; var enclosingSymbol = semanticModel.GetEnclosingSymbol (position, cancellationToken) as INamedTypeSymbol; // Only inside classes and structs if (enclosingSymbol == null || !(enclosingSymbol.TypeKind == TypeKind.Struct || enclosingSymbol.TypeKind == TypeKind.Class)) { return Enumerable.Empty<CompletionData> (); } if (!IsPartialCompletionContext (tree, position, cancellationToken/*, out modifiers*/, out token)) { if (enclosingSymbol != null && (token.IsKind (SyntaxKind.OpenBraceToken) || token.IsKind (SyntaxKind.CloseBraceToken) || token.IsKind (SyntaxKind.SemicolonToken))) { return CreateCompletionData (engine, semanticModel, position, enclosingSymbol, token, false, cancellationToken); } return Enumerable.Empty<CompletionData> (); } return CreateCompletionData (engine, semanticModel, position, enclosingSymbol, token, true, cancellationToken); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var semanticModel = ctx.SemanticModel; if (ctx.TargetToken.Parent != null && ctx.TargetToken.Parent.Parent != null && ctx.TargetToken.Parent.Parent.IsKind(SyntaxKind.Argument)) { SourceText text; if (!completionContext.Document.TryGetText (out text)) { text = await completionContext.Document.GetTextAsync (); } var currentChar = text [completionContext.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 Enumerable.Empty<CompletionData> (); } var formatArgument = GetFormatItemNumber(document, position); var invocationExpression = ctx.TargetToken.Parent.Parent.Parent.Parent as InvocationExpressionSyntax; return GetFormatCompletionData(engine, semanticModel, invocationExpression, formatArgument, currentChar); } return Enumerable.Empty<CompletionData> (); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var targetToken = tree.FindTokenOnLeftOfPosition(position, cancellationToken).GetPreviousTokenIfTouchingWord(position); if (targetToken.IsKind(SyntaxKind.AliasKeyword) && targetToken.Parent.IsKind(SyntaxKind.ExternAliasDirective)) { var compilation = await document.GetCSharpCompilationAsync(cancellationToken).ConfigureAwait(false); var aliases = compilation.ExternalReferences.Where(r => r.Properties.Aliases != null).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); foreach (var used in usedAliases) { aliases.Remove (used); } aliases.Remove(MetadataReferenceProperties.GlobalAlias); return aliases.Select (e => engine.Factory.CreateGenericData (this, e, GenericDataType.Undefined)); } } return Enumerable.Empty<CompletionData> (); }
protected override IEnumerable<INamedTypeSymbol> LookupCandidateSymbols(SyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken) { var candidates = base.LookupCandidateSymbols(context, declaredSymbol, cancellationToken); // The base class applies a broad filter when finding candidates, but since C# requires // that all parts have the "partial" modifier, the results can be trimmed further here. return candidates?.Where(symbol => symbol.DeclaringSyntaxReferences.Any(reference => IsPartialTypeDeclaration(reference.GetSyntax(cancellationToken)))); }
public override async Task<bool> IsExclusiveAsync (CompletionContext completionContext, SyntaxContext syntaxContext, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { // We're exclusive if this context could only be an object initializer and not also a // collection initializer. If we're initializing something that could be initialized as // an object or as a collection, say we're not exclusive. That way the rest of // intellisense can be used in the collection intitializer. // // Consider this case: // class c : IEnumerable<int> // { // public void Add(int addend) { } // public int foo; // } // void foo() // { // var b = new c {| // } // There we could initialize b using either an object initializer or a collection // initializer. Since we don't know which the user will use, we'll be non-exclusive, so // the other providers can help the user write the collection initializer, if they want // to. var document = completionContext.Document; var position = completionContext.Position; var tree = await document.GetCSharpSyntaxTreeAsync (cancellationToken).ConfigureAwait (false); if (tree.IsInNonUserCode (position, cancellationToken)) { return false; } var token = tree.FindTokenOnLeftOfPosition (position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord (position); if (token.Parent == null) { return false; } var expression = token.Parent.Parent as ExpressionSyntax; if (expression == null) { return false; } var semanticModel = await document.GetCSharpSemanticModelForNodeAsync (expression, cancellationToken).ConfigureAwait (false); var initializedType = semanticModel.GetTypeInfo (expression, cancellationToken).Type; if (initializedType == null) { return false; } // Non-exclusive if initializedType can be initialized as a collection. if (initializedType.CanSupportCollectionInitializer ()) { return false; } // By default, only our member names will show up. return true; }
protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) { if (symbol is IAliasSymbol) { return (symbol.Name, symbol.Name); } return base.GetDisplayAndInsertionText(symbol, context); }
protected override ValueTuple<string, string> GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) { if (symbol is IAliasSymbol) { return ValueTuple.Create(symbol.Name, symbol.Name); } return base.GetDisplayAndInsertionText(symbol, context); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; return await document.GetUnionResultsFromDocumentAndLinks( UnionCompletionItemComparer.Instance, async (doc, ct) => await GetSpeculativeTCompletions(engine, doc, position, ct).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var syntaxTree = await document.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken) || syntaxTree.GetContainingTypeOrEnumDeclaration(position, cancellationToken) is EnumDeclarationSyntax) { return Enumerable.Empty<CompletionData>(); } // var span = new TextSpan(position, 0); // var semanticModel = await document.GetCSharpSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); if (syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) { var directive = syntaxTree.GetRoot(cancellationToken).FindTokenOnLeftOfPosition(position, includeDirectives: true).GetAncestor<DirectiveTriviaSyntax>(); 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 Enumerable.Empty<CompletionData>(); } return await GetSnippetCompletionItemsAsync(cancellationToken).ConfigureAwait(false); } var tokenLeftOfPosition = syntaxTree.FindTokenOnLeftOfPosition (position, cancellationToken); if (syntaxTree.IsGlobalStatementContext(position, cancellationToken) || syntaxTree.IsExpressionContext(position, tokenLeftOfPosition, true, cancellationToken) || syntaxTree.IsStatementContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsTypeContext(position, cancellationToken) || syntaxTree.IsTypeDeclarationContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsNamespaceContext(position, cancellationToken) || syntaxTree.IsMemberDeclarationContext(position, tokenLeftOfPosition, cancellationToken) || syntaxTree.IsLabelContext(position, cancellationToken)) { return await GetSnippetCompletionItemsAsync(cancellationToken).ConfigureAwait(false); } return Enumerable.Empty<CompletionData>(); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var model = ctx.SemanticModel; var result = new List<CompletionData> (); if (ctx.IsPreProcessorExpressionContext) { var parseOptions = model.SyntaxTree.Options as CSharpParseOptions; foreach (var define in parseOptions.PreprocessorSymbolNames) { result.Add(engine.Factory.CreateGenericData (this, define, GenericDataType.PreprocessorSymbol)); } } return result; }
private CompletionItem CreateCompletionItem( INamedTypeSymbol symbol, SyntaxContext context) { var displayAndInsertionText = GetDisplayAndInsertionText(symbol, context); return SymbolCompletionItem.Create( displayText: displayAndInsertionText.Item1, insertionText: displayAndInsertionText.Item2, symbol: symbol, contextPosition: context.Position, properties: GetProperties(symbol, context), rules: CompletionItemRules.Default); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { // var ctx = await completionContext.GetSyntaxContextAsync (engine.Workspace, cancellationToken).ConfigureAwait (false); var document = completionContext.Document; var semanticModel = ctx.SemanticModel; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(completionContext.Position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var text = await document.GetTextAsync (cancellationToken).ConfigureAwait (false); var startLineNumber = text.Lines.IndexOf (completionContext.Position); // modifiers* override modifiers* type? | Accessibility seenAccessibility; //DeclarationModifiers modifiers; var token = tree.FindTokenOnLeftOfPosition(completionContext.Position, cancellationToken); if (token.Parent == null) return Enumerable.Empty<CompletionData> (); 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 Enumerable.Empty<CompletionData> (); var position = completionContext.Position; var startToken = token.GetPreviousTokenIfTouchingWord(position); ITypeSymbol returnType; SyntaxToken tokenBeforeReturnType; TryDetermineReturnType (startToken, semanticModel, cancellationToken, out returnType, out tokenBeforeReturnType); if (returnType == null) { var enclosingType = semanticModel.GetEnclosingSymbol (position, cancellationToken) as INamedTypeSymbol; if (enclosingType != null && (startToken.IsKind (SyntaxKind.OpenBraceToken) || startToken.IsKind (SyntaxKind.CloseBraceToken) || startToken.IsKind (SyntaxKind.SemicolonToken))) { return CreateCompletionData (engine, semanticModel, position, returnType, Accessibility.NotApplicable, startToken, tokenBeforeReturnType, false, cancellationToken); } } if (!TryDetermineModifiers(ref tokenBeforeReturnType, text, startLineNumber, out seenAccessibility/*, out modifiers*/) || !TryCheckForTrailingTokens (tree, text, startLineNumber, position, cancellationToken)) { return Enumerable.Empty<CompletionData> (); } return CreateCompletionData (engine, semanticModel, position, returnType, seenAccessibility, startToken, tokenBeforeReturnType, true, cancellationToken); }
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); }
protected override async Task<ImmutableArray<ISymbol>> GetPreselectedSymbolsWorker(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { var result = await base.GetPreselectedSymbolsWorker(context, position, options, cancellationToken).ConfigureAwait(false); if (result.Any()) { var type = (ITypeSymbol)result.Single(); var alias = await type.FindApplicableAlias(position, context.SemanticModel, cancellationToken).ConfigureAwait(false); if (alias != null) { return ImmutableArray.Create(alias); } } return result; }
protected override CompletionItem CreateItem( string displayText, string insertionText, List<ISymbol> symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { return SymbolCompletionItem.Create( displayText: displayText, insertionText: insertionText, filterText: GetFilterText(symbols[0], displayText, context), contextPosition: context.Position, symbols: symbols, supportedPlatforms: supportedPlatformData, matchPriority: MatchPriority.Preselect, // Always preselect tags: s_Tags, rules: GetCompletionItemRules(symbols, context)); }
/// <summary> /// Given a list of symbols, creates the list of completion items for them. /// </summary> protected IEnumerable<CompletionItem> CreateItems( IEnumerable<ISymbol> symbols, SyntaxContext context, Dictionary<ISymbol, List<ProjectId>> invalidProjectMap, List<ProjectId> totalProjects, bool preselect) { var tree = context.SyntaxTree; var q = from symbol in symbols let texts = GetDisplayAndInsertionText(symbol, context) group symbol by texts into g select this.CreateItem(g.Key.Item1, g.Key.Item2, g.ToList(), context, invalidProjectMap, totalProjects, preselect); return q.ToList(); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var syntaxTree = ctx.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return null; } var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (token.Kind() != SyntaxKind.OpenParenToken && token.Kind() != SyntaxKind.CommaToken) { return null; } var attributeArgumentList = token.Parent as AttributeArgumentListSyntax; var attributeSyntax = token.Parent.Parent as AttributeSyntax; if (attributeSyntax == null || attributeArgumentList == null) { return null; } // We actually want to collect two sets of named parameters to present the user. The // normal named parameters that come from the attribute constructors. These will be // presented like "foo:". And also the named parameters that come from the writable // fields/properties in the attribute. These will be presented like "bar =". var existingNamedParameters = GetExistingNamedParameters(attributeArgumentList, position); var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetCSharpSemanticModelForNodeAsync(attributeSyntax, cancellationToken).ConfigureAwait(false); var nameColonItems = await GetNameColonItemsAsync(engine, workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); var nameEqualsItems = await GetNameEqualsItemsAsync(engine, workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); // If we're after a name= parameter, then we only want to show name= parameters. if (IsAfterNameEqualsArgument(token)) { return nameEqualsItems; } return nameColonItems.Concat(nameEqualsItems); }
protected override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var semanticModel = ctx.SemanticModel; if (info.TriggerCharacter == '\\') { 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 TaskUtil.EmptyEnumerable<CompletionData> (); if (SemanticHighlightingVisitor<int>.IsRegexMatchMethod (symbolInfo)) { if (((ArgumentListSyntax)argument.Parent).Arguments [1] != argument) return TaskUtil.EmptyEnumerable<CompletionData> (); completionResult.AutoSelect = false; return Task.FromResult (GetFormatCompletionData (engine, argument.Expression.ToString () [0] == '@')); } if (SemanticHighlightingVisitor<int>.IsRegexConstructor (symbolInfo)) { if (((ArgumentListSyntax)argument.Parent).Arguments [0] != argument) return TaskUtil.EmptyEnumerable<CompletionData> (); completionResult.AutoSelect = false; return Task.FromResult (GetFormatCompletionData (engine, argument.Expression.ToString () [0] == '@')); } } } 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" ) { var items = new List<CompletionData>(); foreach (var grp in GetGroups (ctx, symbolInfo.Symbol)) { items.Add (engine.Factory.CreateGenericData (this, "Groups[\"" + grp + "\"]", GenericDataType.Undefined)); } return Task.FromResult ((IEnumerable<CompletionData>)items); } } } return TaskUtil.EmptyEnumerable<CompletionData> (); }
protected override CompletionItem CreateItem(string displayText, string insertionText, List<ISymbol> symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { var matchPriority = preselect ? ComputeSymbolMatchPriority(symbols[0]) : MatchPriority.Default; var rules = GetCompletionItemRules(symbols, context, preselect); if (preselect) { rules = rules.WithSelectionBehavior(PreselectedItemSelectionBehavior); } return SymbolCompletionItem.Create( displayText: displayText, insertionText: insertionText, filterText: GetFilterText(symbols[0], displayText, context), contextPosition: context.Position, symbols: symbols, supportedPlatforms: supportedPlatformData, matchPriority: matchPriority, rules: rules); }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult result, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var list = new List<CompletionData> (); var newExpression = GetObjectCreationNewExpression (ctx.SyntaxTree, completionContext.Position, cancellationToken); if (newExpression == null) { if (ctx.SyntaxTree.IsInNonUserCode(completionContext.Position, cancellationToken) || ctx.SyntaxTree.IsPreProcessorDirectiveContext(completionContext.Position, cancellationToken)) return Enumerable.Empty<CompletionData> (); // if (!nkr.IsValid (completionContext.Position, ctx.CSharpSyntaxContext, cancellationToken)) // return Enumerable.Empty<ICompletionData> (); var tokenOnLeftOfPosition = ctx.SyntaxTree.FindTokenOnLeftOfPosition (completionContext.Position, cancellationToken); if (!tokenOnLeftOfPosition.IsKind (SyntaxKind.EqualsToken) && !tokenOnLeftOfPosition.Parent.IsKind (SyntaxKind.EqualsValueClause)) return Enumerable.Empty<CompletionData> (); foreach (var inferredType in SyntaxContext.InferenceService.InferTypes (ctx.CSharpSyntaxContext.SemanticModel, completionContext.Position, cancellationToken)) { if (inferredType.IsEnumType () || inferredType.IsInterfaceType () || inferredType.IsAbstract) continue; foreach (var symbol in await GetPreselectedSymbolsWorker(ctx.CSharpSyntaxContext, inferredType, completionContext.Position - 1, cancellationToken)) { var symbolCompletionData = engine.Factory.CreateObjectCreation (this, inferredType, symbol, completionContext.Position, false); list.Add (symbolCompletionData); } } return list; } var type = SyntaxContext.InferenceService.InferType (ctx.CSharpSyntaxContext.SemanticModel, newExpression, objectAsDefault: false, cancellationToken: cancellationToken); foreach (var symbol in await GetPreselectedSymbolsWorker(ctx.CSharpSyntaxContext, type, completionContext.Position, cancellationToken)) { var symbolCompletionData = engine.Factory.CreateObjectCreation (this, type, symbol, newExpression.SpanStart, true); list.Add (symbolCompletionData); if (string.IsNullOrEmpty (result.DefaultCompletionString)) result.DefaultCompletionString = symbolCompletionData.DisplayText; } foreach (var keyword in primitiveTypesKeywords) { list.Add (engine.Factory.CreateGenericData (this, keyword, GenericDataType.Keyword)); } return list; }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var position = completionContext.Position; var document = completionContext.Document; var syntaxTree = ctx.SyntaxTree; if (syntaxTree.IsInNonUserCode(position, cancellationToken) || syntaxTree.IsPreProcessorDirectiveContext(position, cancellationToken)) return Enumerable.Empty<CompletionData> (); if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var ma = ctx.LeftToken.Parent as MemberAccessExpressionSyntax; if (ma == null) return Enumerable.Empty<CompletionData> (); var model = ctx.CSharpSyntaxContext.SemanticModel; var symbolInfo = model.GetSymbolInfo (ma.Expression); if (symbolInfo.Symbol == null) return Enumerable.Empty<CompletionData> (); var list = new List<CompletionData> (); var within = model.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); var addedSymbols = new HashSet<string> (); foreach (var ifStmSyntax in ma.Expression.AncestorsAndSelf ().OfType<IfStatementSyntax> ()) { var condition = ifStmSyntax.Condition.SkipParens (); if (condition == null || !condition.IsKind (SyntaxKind.IsExpression)) continue; 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 (engine, ma.Expression, type, within, list, addedSymbols, cancellationToken); } } } return list; }
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var model = ctx.SemanticModel; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(completionContext.Position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var token = tree.FindTokenOnLeftOfPosition(completionContext.Position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) return Enumerable.Empty<CompletionData> (); var result = new List<CompletionData> (); 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(completionContext.Position, model, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(completionResult.DefaultCompletionString)) completionResult.DefaultCompletionString = type.Name; result.Add (engine.Factory.CreateSymbolCompletionData(this, type, RoslynCompletionData.SafeMinimalDisplayString (type, model, completionContext.Position, SymbolDisplayFormat.CSharpErrorMessageFormat))); foreach (IFieldSymbol field in type.GetMembers().OfType<IFieldSymbol>()) { if (field.DeclaredAccessibility == Accessibility.Public && (field.IsConst || field.IsStatic)) { result.Add (engine.Factory.CreateEnumMemberCompletionData(this, alias, field)); } } } return result; }
protected virtual IEnumerable<INamedTypeSymbol> LookupCandidateSymbols(SyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken) { if (declaredSymbol == null) { throw new ArgumentNullException(nameof(declaredSymbol)); } SemanticModel semanticModel = context.SemanticModel; INamespaceOrTypeSymbol containingSymbol = declaredSymbol.ContainingSymbol as INamespaceOrTypeSymbol; if (containingSymbol == null) { return SpecializedCollections.EmptyEnumerable<INamedTypeSymbol>(); } return semanticModel.LookupNamespacesAndTypes(context.Position, containingSymbol) .OfType<INamedTypeSymbol>() .Where(symbol => declaredSymbol.TypeKind == symbol.TypeKind && NotNewDeclaredMember(symbol, context) && InSameProject(symbol, semanticModel.Compilation)); }
protected override async Task<ImmutableArray<ISymbol>> GetPreselectedSymbolsWorker(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { var recommender = context.GetLanguageService<IRecommendationService>(); var typeInferrer = context.GetLanguageService<ITypeInferenceService>(); var inferredTypes = typeInferrer.InferTypes(context.SemanticModel, position, cancellationToken) .Where(t => t.SpecialType != SpecialType.System_Void) .ToSet(); if (inferredTypes.Count == 0) { return ImmutableArray<ISymbol>.Empty; } var symbols = await recommender.GetRecommendedSymbolsAtPositionAsync( context.Workspace, context.SemanticModel, position, options, cancellationToken).ConfigureAwait(false); // Don't preselect intrinsic type symbols so we can preselect their keywords instead. return symbols.WhereAsArray(s => inferredTypes.Contains(GetSymbolType(s)) && !IsInstrinsic(s)); }
public override async Task<bool> IsExclusiveAsync (CompletionContext completionContext, SyntaxContext ctx, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var tree = ctx.SyntaxTree; //DeclarationModifiers modifiers; SyntaxToken token; var semanticModel = ctx.SemanticModel; var enclosingSymbol = semanticModel.GetEnclosingSymbol (position, cancellationToken) as INamedTypeSymbol; // Only inside classes and structs if (enclosingSymbol == null || !(enclosingSymbol.TypeKind == TypeKind.Struct || enclosingSymbol.TypeKind == TypeKind.Class)) { return false; } if (!IsPartialCompletionContext (tree, position, cancellationToken/*, out modifiers*/, out token)) { return false; } return true; }
private Task <ImmutableArray <ISymbol> > GetSymbolsAsync(int position, bool preselect, SyntaxContext context, OptionSet options, CancellationToken cancellationToken) { try { return(preselect ? GetPreselectedSymbolsAsync(context, position, options, cancellationToken) : GetSymbolsAsync(context, position, options, cancellationToken)); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
private static bool ShouldSoftSelectInArgumentList(CompletionContext completionContext, SyntaxContext context, bool preselect) { return(!preselect && completionContext.Trigger.Kind == CompletionTriggerKind.Insertion && context.IsOnArgumentListBracketOrComma && IsArgumentListTriggerCharacter(completionContext.Trigger.Character)); }
protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText(ISymbol symbol, SyntaxContext context) => CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context);
protected override bool ShouldProvideCompletion(CompletionContext completionContext, SyntaxContext syntaxContext) => syntaxContext.IsTypeContext;
protected abstract Task <ImmutableArray <ISymbol> > GetSymbolsWorker(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken);
protected abstract (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context);
protected virtual Task <ImmutableArray <ISymbol> > GetPreselectedSymbolsWorker(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); }
protected async override Task <bool> ShouldProvidePreselectedItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, Document document, int position, Lazy <ImmutableArray <ITypeSymbol> > inferredTypes, OptionSet options) { var sourceText = await document.GetTextAsync(CancellationToken.None).ConfigureAwait(false); if (ShouldTriggerInArgumentLists(sourceText, options)) { // Avoid preselection & hard selection when triggered via insertion in an argument list. // If an item is hard selected, then a user trying to type MethodCall() will get // MethodCall(someVariable) instead. We need only soft selected items to prevent this. if (completionContext.Trigger.Kind == CompletionTriggerKind.Insertion && position > 0 && await IsTriggerInArgumentListAsync(document, position - 1, CancellationToken.None).ConfigureAwait(false) == true) { return(false); } } return(true); }
private Task <ImmutableArray <ISymbol> > GetSymbolsWorker(int position, bool preselect, SyntaxContext context, OptionSet options, CancellationToken cancellationToken) { return(preselect ? GetPreselectedSymbolsWorker(context, position, options, cancellationToken) : GetSymbolsWorker(context, position, options, cancellationToken)); }
protected override async Task <ImmutableArray <ISymbol> > GetPreselectedSymbolsWorker(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { var recommender = context.GetLanguageService <IRecommendationService>(); var typeInferrer = context.GetLanguageService <ITypeInferenceService>(); var inferredTypes = typeInferrer.InferTypes(context.SemanticModel, position, cancellationToken) .Where(t => t.SpecialType != SpecialType.System_Void) .ToSet(); if (inferredTypes.Count == 0) { return(ImmutableArray <ISymbol> .Empty); } var symbols = await recommender.GetRecommendedSymbolsAtPositionAsync( context.Workspace, context.SemanticModel, context.Position, options, cancellationToken).ConfigureAwait(false); // Don't preselect intrinsic type symbols so we can preselect their keywords instead. return(symbols.WhereAsArray(s => inferredTypes.Contains(GetSymbolType(s)) && !IsInstrinsic(s))); }
protected override Task <ImmutableArray <ISymbol> > GetSymbolsAsync(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { var recommender = context.GetLanguageService <IRecommendationService>(); return(recommender.GetRecommendedSymbolsAtPositionAsync(context.Workspace, context.SemanticModel, position, options, cancellationToken)); }
protected abstract ImmutableDictionary <string, string> GetProperties( INamedTypeSymbol symbol, SyntaxContext context);
private static bool NotNewDeclaredMember(INamedTypeSymbol symbol, SyntaxContext context) { return(symbol.DeclaringSyntaxReferences .Select(reference => reference.GetSyntax()) .Any(node => !(node.SyntaxTree == context.SyntaxTree && node.Span.IntersectsWith(context.Position)))); }
protected abstract CompletionItemRules GetCompletionItemRules(IReadOnlyList <ISymbol> symbols, SyntaxContext context);
protected override Task <ImmutableArray <ISymbol> > GetPreselectedSymbolsWorker( SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { return(GetSymbolsWorkerInternal(context, position, options, preselect: true, cancellationToken)); }
protected override async Task AddCompletionItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, HashSet <string> namespacesInScope, bool isExpandedCompletion, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Completion_TypeImportCompletionProvider_GetCompletionItemsAsync, cancellationToken)) { var telemetryCounter = new TelemetryCounter(); var typeImportCompletionService = completionContext.Document.GetRequiredLanguageService <ITypeImportCompletionService>(); var itemsFromAllAssemblies = await typeImportCompletionService.GetAllTopLevelTypesAsync( completionContext.Document.Project, syntaxContext, forceCacheCreation : isExpandedCompletion, completionContext.CompletionOptions, cancellationToken).ConfigureAwait(false); if (itemsFromAllAssemblies == null) { telemetryCounter.CacheMiss = true; } else { var aliasTargetNamespaceToTypeNameMap = GetAliasTypeDictionary(completionContext.Document, syntaxContext, cancellationToken); foreach (var items in itemsFromAllAssemblies) { AddItems(items, completionContext, namespacesInScope, aliasTargetNamespaceToTypeNameMap, telemetryCounter); } } telemetryCounter.Report(); } }
protected async override Task <IEnumerable <CompletionData> > GetItemsWorkerAsync(CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { // var ctx = await completionContext.GetSyntaxContextAsync (engine.Workspace, cancellationToken).ConfigureAwait (false); var document = completionContext.Document; var semanticModel = ctx.SemanticModel; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(completionContext.Position, cancellationToken)) { return(Enumerable.Empty <CompletionData> ()); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var startLineNumber = text.Lines.IndexOf(completionContext.Position); // modifiers* override modifiers* type? | Accessibility seenAccessibility; //DeclarationModifiers modifiers; var token = tree.FindTokenOnLeftOfPosition(completionContext.Position, cancellationToken); if (token.Parent == null) { return(Enumerable.Empty <CompletionData> ()); } 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(Enumerable.Empty <CompletionData> ()); } var position = completionContext.Position; var startToken = token.GetPreviousTokenIfTouchingWord(position); ITypeSymbol returnType; SyntaxToken tokenBeforeReturnType; TryDetermineReturnType(startToken, semanticModel, cancellationToken, out returnType, out tokenBeforeReturnType); if (returnType == null) { var enclosingType = semanticModel.GetEnclosingSymbol(position, cancellationToken) as INamedTypeSymbol; if (enclosingType != null && (startToken.IsKind(SyntaxKind.OpenBraceToken) || startToken.IsKind(SyntaxKind.CloseBraceToken) || startToken.IsKind(SyntaxKind.SemicolonToken))) { return(CreateCompletionData(engine, semanticModel, position, returnType, Accessibility.NotApplicable, startToken, tokenBeforeReturnType, false, cancellationToken)); } } if (!TryDetermineModifiers(ref tokenBeforeReturnType, text, startLineNumber, out seenAccessibility /*, out modifiers*/) || !TryCheckForTrailingTokens(tree, text, startLineNumber, position, cancellationToken)) { return(Enumerable.Empty <CompletionData> ()); } return(CreateCompletionData(engine, semanticModel, position, returnType, seenAccessibility, startToken, tokenBeforeReturnType, true, cancellationToken)); }
protected override async Task <ImmutableArray <ISymbol> > GetPreselectedSymbolsAsync(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { var recommender = context.GetLanguageService <IRecommendationService>(); var inferredTypes = context.InferredTypes.Where(t => t.SpecialType != SpecialType.System_Void).ToSet(); if (inferredTypes.Count == 0) { return(ImmutableArray <ISymbol> .Empty); } var symbols = await recommender.GetRecommendedSymbolsAtPositionAsync( context.Workspace, context.SemanticModel, context.Position, options, cancellationToken).ConfigureAwait(false); // Don't preselect intrinsic type symbols so we can preselect their keywords instead. We will also ignore nullability for purposes of preselection // -- if a method is returning a string? but we've inferred we're assigning to a string or vice versa we'll still count those as the same. return(symbols.WhereAsArray(s => inferredTypes.Contains(GetSymbolType(s), SymbolEqualityComparer.Default) && !IsInstrinsic(s))); }
protected override Task <ImmutableArray <ISymbol> > GetSymbolsAsync(SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { return(Recommender.GetImmutableRecommendedSymbolsAtPositionAsync( context.SemanticModel, position, context.Workspace, options, cancellationToken)); }
private async Task AddCompletionItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, TelemetryCounter telemetryCounter, CancellationToken cancellationToken) { var document = completionContext.Document; var project = document.Project; var workspace = project.Solution.Workspace; var typeImportCompletionService = document.GetLanguageService <ITypeImportCompletionService>(); // Find all namespaces in scope at current cursor location, // which will be used to filter so the provider only returns out-of-scope types. var namespacesInScope = GetNamespacesInScope(document, syntaxContext, cancellationToken); var tasksToGetCompletionItems = ArrayBuilder <Task <ImmutableArray <CompletionItem> > > .GetInstance(); // Get completion items from current project. var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); tasksToGetCompletionItems.Add(Task.Run(() => typeImportCompletionService.GetTopLevelTypesAsync( project, syntaxContext, isInternalsVisible: true, cancellationToken))); // Get declarations from directly referenced projects and PEs. // This can be parallelized because we don't add items to CompletionContext // until all the collected tasks are completed. var referencedAssemblySymbols = compilation.GetReferencedAssemblySymbols(); tasksToGetCompletionItems.AddRange( referencedAssemblySymbols.Select(symbol => Task.Run(() => HandleReferenceAsync(symbol)))); // We want to timebox the operation that might need to traverse all the type symbols and populate the cache, // the idea is not to block completion for too long (likely to happen the first time import completion is triggered). // The trade-off is we might not provide unimported types until the cache is warmed up. var combinedTask = Task.WhenAll(tasksToGetCompletionItems.ToImmutableAndFree()); if (await Task.WhenAny(combinedTask, Task.Delay(TimeoutInMilliseconds, cancellationToken)).ConfigureAwait(false) == combinedTask) { // No timeout. We now have all completion items ready. var completionItemsToAdd = await combinedTask.ConfigureAwait(false); foreach (var completionItems in completionItemsToAdd) { AddItems(completionItems, completionContext, namespacesInScope, telemetryCounter); } } else { // If timed out, we don't want to cancel the computation so next time the cache would be populated. // We do not keep track if previous compuation for a given project/PE reference is still running. So there's a chance // we queue same computation again later. However, we expect such computation for an individual reference to be relatively // fast so the actual cycles wasted would be insignificant. telemetryCounter.TimedOut = true; } telemetryCounter.ReferenceCount = referencedAssemblySymbols.Length; return; async Task <ImmutableArray <CompletionItem> > HandleReferenceAsync(IAssemblySymbol referencedAssemblySymbol) { cancellationToken.ThrowIfCancellationRequested(); // Skip reference with only non-global alias. var metadataReference = compilation.GetMetadataReference(referencedAssemblySymbol); if (metadataReference.Properties.Aliases.IsEmpty || metadataReference.Properties.Aliases.Any(alias => alias == MetadataReferenceProperties.GlobalAlias)) { var assemblyProject = project.Solution.GetProject(referencedAssemblySymbol, cancellationToken); if (assemblyProject != null && assemblyProject.SupportsCompilation) { return(await typeImportCompletionService.GetTopLevelTypesAsync( assemblyProject, syntaxContext, isInternalsVisible : compilation.Assembly.IsSameAssemblyOrHasFriendAccessTo(referencedAssemblySymbol), cancellationToken).ConfigureAwait(false)); } else if (metadataReference is PortableExecutableReference peReference) { return(typeImportCompletionService.GetTopLevelTypesFromPEReference( project.Solution, compilation, peReference, syntaxContext, isInternalsVisible: compilation.Assembly.IsSameAssemblyOrHasFriendAccessTo(referencedAssemblySymbol), cancellationToken)); } } return(ImmutableArray <CompletionItem> .Empty); }
/// <summary> /// The decision for whether to provide preselected items can be contextual, e.g. based on trigger character and syntax location /// </summary> protected virtual Task <bool> ShouldProvidePreselectedItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, Document document, int position, Lazy <ImmutableArray <ITypeSymbol> > inferredTypes, OptionSet options) => SpecializedTasks.True;
protected async override Task <IEnumerable <CompletionData> > GetItemsWorkerAsync(CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var model = ctx.SemanticModel; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(completionContext.Position, cancellationToken)) { return(Enumerable.Empty <CompletionData> ()); } var token = tree.FindTokenOnLeftOfPosition(completionContext.Position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return(Enumerable.Empty <CompletionData> ()); } var result = new List <CompletionData> (); // 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(Enumerable.Empty <CompletionData> ()); } 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(completionContext.Position, model, cancellationToken).ConfigureAwait(false); var displayString = RoslynCompletionData.SafeMinimalDisplayString(type, model, completionContext.Position, SymbolDisplayFormat.CSharpErrorMessageFormat); if (string.IsNullOrEmpty(completionResult.DefaultCompletionString)) { completionResult.DefaultCompletionString = displayString; completionResult.AutoCompleteEmptyMatch = true; } if (!IsReachable(model, type, token.Parent)) { result.Add(engine.Factory.CreateSymbolCompletionData(this, type, displayString)); } foreach (IFieldSymbol field in type.GetMembers().OfType <IFieldSymbol> ()) { if (field.DeclaredAccessibility == Accessibility.Public && (field.IsConst || field.IsStatic)) { result.Add(engine.Factory.CreateEnumMemberCompletionData(this, alias, field)); } } } return(result); }
protected abstract CompletionItemRules GetCompletionItemRules(List <ISymbol> symbols, SyntaxContext context, bool preselect);
protected async override Task<IEnumerable<CompletionData>> GetItemsWorkerAsync (CompletionResult completionResult, CompletionEngine engine, CompletionContext completionContext, CompletionTriggerInfo info, SyntaxContext ctx, CancellationToken cancellationToken) { var document = completionContext.Document; var position = completionContext.Position; var tree = ctx.SyntaxTree; if (tree.IsInNonUserCode(position, cancellationToken)) return Enumerable.Empty<CompletionData> (); var targetToken = tree.FindTokenOnLeftOfPosition(position, cancellationToken).GetPreviousTokenIfTouchingWord(position); if (targetToken.IsKind(SyntaxKind.AliasKeyword) && targetToken.Parent.IsKind(SyntaxKind.ExternAliasDirective)) { var compilation = await document.GetCSharpCompilationAsync(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); foreach (var used in usedAliases) { aliases.Remove (used); } aliases.Remove(MetadataReferenceProperties.GlobalAlias); return aliases.Select (e => engine.Factory.CreateGenericData (this, e, GenericDataType.Undefined)); } } return Enumerable.Empty<CompletionData> (); }
public bool IsApplicable(SyntaxContext syntaxContext, Options.Options options) { return(true); }
private Task <ImmutableArray <ISymbol> > GetSymbolsWorkerInternal( SyntaxContext context, int position, OptionSet options, bool preselect, CancellationToken cancellationToken) { var newExpression = GetObjectCreationNewExpression(context.SyntaxTree, position, cancellationToken); if (newExpression == null) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } var typeInferenceService = context.GetLanguageService <ITypeInferenceService>(); var type = typeInferenceService.InferType( context.SemanticModel, position, objectAsDefault: false, cancellationToken: cancellationToken); // Unwrap an array type fully. We only want to offer the underlying element type in the // list of completion items. var isArray = false; while (type is IArrayTypeSymbol) { isArray = true; type = ((IArrayTypeSymbol)type).ElementType; } if (type == null || (isArray && preselect)) { // In the case of array creation, we don't offer a preselected/hard-selected item because // the user may want an implicitly-typed array creation return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } // Unwrap nullable if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); } if (type.SpecialType == SpecialType.System_Void) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } if (type.ContainsAnonymousType()) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } if (!type.CanBeReferencedByName) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } // Normally the user can't say things like "new IList". Except for "IList[] x = new |". // In this case we do want to allow them to preselect certain types in the completion // list even if they can't new them directly. if (!isArray) { if (type.TypeKind == TypeKind.Interface || type.TypeKind == TypeKind.Pointer || type.TypeKind == TypeKind.Dynamic || type.IsAbstract) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } if (type.TypeKind == TypeKind.TypeParameter && !((ITypeParameterSymbol)type).HasConstructorConstraint) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } } if (!type.IsEditorBrowsable(options.GetOption(RecommendationOptions.HideAdvancedMembers, context.SemanticModel.Language), context.SemanticModel.Compilation)) { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } return(Task.FromResult(ImmutableArray.Create((ISymbol)type))); }
protected abstract Task AddCompletionItemsAsync(CompletionContext completionContext, SyntaxContext syntaxContext, HashSet <string> namespacesInScope, CancellationToken cancellationToken);
internal ScriptSourceFile(FileInfo scriptFile, SyntaxContext syntaxContext) { this.ScriptFile = scriptFile; this.Reader = new StreamReader(scriptFile.OpenRead(), true); this.SyntaxContext = syntaxContext; }
private bool IsCandidateProject(SyntaxContext context, CancellationToken cancellationToken) { var syntaxFacts = context.GetLanguageService <ISyntaxFactsService>(); return(!syntaxFacts.IsInInactiveRegion(context.SyntaxTree, context.Position, cancellationToken)); }
protected override CompletionItem CreateItem(string displayText, string insertionText, List <ISymbol> symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { var rules = GetCompletionItemRules(symbols, context, preselect); var matchPriority = preselect ? ComputeSymbolMatchPriority(symbols[0]) : MatchPriority.Default; rules = rules.WithMatchPriority(matchPriority); if (preselect) { rules = rules.WithSelectionBehavior(PreselectedItemSelectionBehavior); } return(SymbolCompletionItem.CreateWithNameAndKind( displayText: displayText, symbols: symbols, rules: rules, contextPosition: context.Position, insertionText: insertionText, filterText: GetFilterText(symbols[0], displayText, context), supportedPlatforms: supportedPlatformData)); }