public async Task GetDescriptionAsync_DoesNotAddDescriptionWhenPropertyAbsent() { // Arrange var document = CreateDocument(); var item = CompletionItem.Create("TestDirective"); var codeDocumentProvider = new Mock <RazorCodeDocumentProvider>(); var completionProvider = new RazorDirectiveCompletionProvider( new Lazy <RazorCodeDocumentProvider>(() => codeDocumentProvider.Object), CompletionProviderDependencies, TextBufferProvider); // Act var description = await completionProvider.GetDescriptionAsync(document, item, CancellationToken.None); // Assert Assert.Empty(description.TaggedParts); Assert.Equal(string.Empty, description.Text); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { //Do not provide completion with ctrl+space if (context.Trigger.Kind == CompletionTriggerKind.InvokeAndCommitIfUnique) { return; } var document = context.Document; var cancellationToken = context.CancellationToken; var startPosition = context.Position; //Get code content var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); //Find exact starting position by checking code syntax while (char.IsLetter(text[startPosition - 1])) { startPosition--; } var replacmentSpan = TextSpan.FromBounds(startPosition, context.Position); FillLicenses(replacmentSpan); //Fill intelliSense dialog box with suggested data foreach (var item in LicensePlates) { var textChange = item.Change.TextChange; var properties = ImmutableDictionary.CreateBuilder <string, string>(); properties.Add(StartKey, textChange.Span.Start.ToString()); properties.Add(LengthKey, textChange.Span.Length.ToString()); properties.Add(NewTextKey, textChange.NewText); context.AddItem(CompletionItem.Create( displayText: item.City, inlineDescription: item.Code, properties: properties.ToImmutable())); } context.IsExclusive = true; }
public static CompletionItem Create(string name, int arity, string containingNamespace, Glyph glyph, string genericTypeSuffix, CompletionItemFlags flags, string?symbolKeyData) { ImmutableDictionary <string, string>?properties = null; if (symbolKeyData != null || arity > 0) { var builder = PooledDictionary <string, string> .GetInstance(); if (symbolKeyData != null) { builder.Add(SymbolKeyData, symbolKeyData); } else { // We don't need arity to recover symbol if we already have SymbolKeyData or it's 0. // (but it still needed below to decide whether to show generic suffix) builder.Add(TypeAritySuffixName, AbstractDeclaredSymbolInfoFactoryService.GetMetadataAritySuffix(arity)); } properties = builder.ToImmutableDictionaryAndFree(); } // Add tildes (ASCII: 126) to name and namespace as sort text: // 1. '~' before type name makes import items show after in-scope items // 2. ' ' before namespace makes types with identical type name but from different namespace all show up in the list, // it also makes sure type with shorter name shows first, e.g. 'SomeType` before 'SomeTypeWithLongerName'. var sortTextBuilder = PooledStringBuilder.GetInstance(); sortTextBuilder.Builder.AppendFormat(SortTextFormat, name, containingNamespace); var item = CompletionItem.Create( displayText: name, sortText: sortTextBuilder.ToStringAndFree(), properties: properties, tags: GlyphTags.GetTags(glyph), rules: CompletionItemRules.Default, displayTextPrefix: null, displayTextSuffix: arity == 0 ? string.Empty : genericTypeSuffix, inlineDescription: containingNamespace); item.Flags = flags; return(item); }
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 IEnumerable <CompletionItem> GetCompletionsWorker(string pathSoFar) { var comma = pathSoFar.IndexOf(','); if (comma >= 0) { var path = pathSoFar.Substring(0, comma); return(from identity in GetAssemblyIdentities(path) let text = identity.GetDisplayName() select CompletionItem.Create(text, span : _textChangeSpan, rules : _itemRules)); } return(from displayName in _lazyAssemblySimpleNames.Value select CommonCompletionItem.Create( displayName, description : GlobalAssemblyCache.Instance.ResolvePartialName(displayName).GetDisplayName().ToSymbolDisplayParts(), glyph : Microsoft.CodeAnalysis.Glyph.Assembly, span : _textChangeSpan, rules : _itemRules)); }
public static CompletionItem CreateAttributeItemWithoutSuffix(CompletionItem attributeItem, string attributeNameWithoutSuffix) { Debug.Assert(!attributeItem.Properties.ContainsKey(AttributeFullName)); // Remember the full type name so we can get the symbol when description is displayed. var newProperties = attributeItem.Properties.Add(AttributeFullName, attributeItem.DisplayText); var sortTextBuilder = PooledStringBuilder.GetInstance(); sortTextBuilder.Builder.AppendFormat(SortTextFormat, attributeNameWithoutSuffix, attributeItem.InlineDescription); return(CompletionItem.Create( displayText: attributeNameWithoutSuffix, sortText: sortTextBuilder.ToStringAndFree(), properties: newProperties, tags: attributeItem.Tags, rules: attributeItem.Rules, displayTextPrefix: attributeItem.DisplayTextPrefix, displayTextSuffix: attributeItem.DisplayTextSuffix, inlineDescription: attributeItem.InlineDescription)); }
public static CompletionItem CreateCompletionItem(ISymbol symbol, SyntaxContext context, bool sortLast) { var accessabilityTag = GetAccessabilityTag(symbol); var kindTag = GetSymbolKindTag(symbol); var tags = ImmutableArray.Create(kindTag, accessabilityTag); // Make those items less prioritized var rules = CompletionItemRules.Create( matchPriority: -1 ); // In original Roslyn SymbolCompletionProvider SymbolsProperty is set // for all items. However, for huge items quantity // encoding has significant performance impact. We will put it in GetDescriptionAsync. var fullSymbolName = symbol.GetFullyQualifiedName(); var nsName = symbol.GetNamespace(); (string displayText, string insertText) = GetDisplayInsertText(symbol, context, nsName); var props = ImmutableDictionary.CreateBuilder(StringComparer.Ordinal, StringComparer.Ordinal); props.Add(CompletionItemProperties.ContextPosition, context.Position.ToString()); props.Add(CompletionItemProperties.SymbolName, symbol.Name); props.Add(CompletionItemProperties.FullSymbolName, fullSymbolName); props.Add(CompletionItemProperties.Namespace, nsName); props.Add(CompletionItemProperties.InsertText, insertText); // Add namespace to the end so items with same name would be displayed var sortText = GetSortText(symbol.Name, nsName, sortLast); return(CompletionItem.Create( displayText: displayText, sortText: sortText, filterText: insertText, properties: props.ToImmutable(), rules: rules, tags: tags)); }
public async Task GetDescriptionAsync_AddsDirectiveDescriptionIfPropertyExists() { // Arrange var document = CreateDocument(); var expectedDescription = "The expected description"; var item = CompletionItem.Create("TestDirective") .WithProperties((new Dictionary <string, string>() { [RazorDirectiveCompletionProvider.DescriptionKey] = expectedDescription, }).ToImmutableDictionary()); var codeDocumentProvider = new Mock <RazorCodeDocumentProvider>(); var completionProvider = new RazorDirectiveCompletionProvider(new Lazy <RazorCodeDocumentProvider>(() => codeDocumentProvider.Object)); // Act var description = await completionProvider.GetDescriptionAsync(document, item, CancellationToken.None); // Assert var part = Assert.Single(description.TaggedParts); Assert.Equal(TextTags.Text, part.Tag); Assert.Equal(expectedDescription, part.Text); Assert.Equal(expectedDescription, description.Text); }
public static async Task <dynamic> GetCodeCompletion(SourceInfo sourceInfo, ILogger log) { var thisAssembly = typeof(CompleteCode).Assembly; var loadContext = AssemblyLoadContext.GetLoadContext(thisAssembly); var refs = CompileResources.PortableExecutableCompletionReferences; var usings = new List <string>(); var allusingsInCode = sourceInfo.SourceCode.Split(new string[] { "using " }, StringSplitOptions.None); foreach (var item in allusingsInCode) { if (!string.IsNullOrWhiteSpace(item)) { usings.Add(item.Split(';')[0]); } } List <Assembly> assemblies = loadContext.Assemblies.Where(a => !a.IsDynamic && File.Exists(a.Location)).ToList(); var partTypes = MefHostServices.DefaultAssemblies.Concat(assemblies) .Distinct()? .SelectMany(x => x?.GetTypes())? .ToArray(); var compositionContext = new ContainerConfiguration() .WithParts(partTypes) .CreateContainer(); var host = MefHostServices.Create(compositionContext); var workspace = new AdhocWorkspace(host); var scriptCode = sourceInfo.SourceCode; var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: usings); if (_ref == null || !_ref.Any()) { var _refs = assemblies .Select(asm => MetadataReference.CreateFromFile(asm.Location)) .ToArray(); _ref = new PortableExecutableReference[0]; _ref = _refs.Concatenate(_refs); } if (_ref?.Count() > 0) { var _ref = refs.Concatenate(new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var scriptProjectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Script", "Script", LanguageNames.CSharp, isSubmission: true) .WithMetadataReferences(refs) .WithCompilationOptions(compilationOptions); var scriptProject = workspace.AddProject(scriptProjectInfo); var scriptDocumentInfo = DocumentInfo.Create( DocumentId.CreateNewId(scriptProject.Id), "Script", sourceCodeKind: SourceCodeKind.Script, loader: TextLoader.From(TextAndVersion.Create(SourceText.From(scriptCode), VersionStamp.Create()))); var scriptDocument = workspace.AddDocument(scriptDocumentInfo); // cursor position is at the end var position = sourceInfo.LineNumberOffsetFromTemplate; var completionService = CompletionService.GetService(scriptDocument); var results = await completionService.GetCompletionsAsync(scriptDocument, position); if (results == null && sourceInfo.LineNumberOffsetFromTemplate < sourceInfo.SourceCode.Length) { sourceInfo.LineNumberOffsetFromTemplate++; await GetCodeCompletion(sourceInfo, log); } if (sourceInfo.SourceCode[sourceInfo.LineNumberOffsetFromTemplate - 1].ToString() == "(") { sourceInfo.LineNumberOffsetFromTemplate--; results = completionService.GetCompletionsAsync(scriptDocument, sourceInfo.LineNumberOffsetFromTemplate).Result; } //Method parameters List <string> overloads = GetMethodParams(scriptCode, position, log); if (overloads?.Count > 0) { ImmutableArray <CompletionItem> .Builder builder = ImmutableArray.CreateBuilder <CompletionItem>(); foreach (var item in overloads) { string DisplayText = item; string insertText = item.Split('(')[1].Split(')')[0]; CompletionItem ci = CompletionItem.Create(insertText, insertText, insertText); builder.Add(ci); } if (builder.Count > 0) { ImmutableArray <CompletionItem> itemlist = builder.ToImmutable(); return(CompletionList.Create(new TextSpan(), itemlist)); } } return(results); } return(null); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // This provider is exported for all workspaces - so limit it to just our workspace & the debugger's intellisense workspace if (context.Document.Project.Solution.Workspace.Kind != WorkspaceKind.AnyCodeRoslynWorkspace && context.Document.Project.Solution.Workspace.Kind != StringConstants.DebuggerIntellisenseWorkspaceKind) { return; } var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient; if (lspClient == null) { return; } var text = await context.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var completionParams = new LSP.CompletionParams { TextDocument = ProtocolConversions.DocumentToTextDocumentIdentifier(context.Document), Position = ProtocolConversions.LinePositionToPosition(text.Lines.GetLinePosition(context.Position)), Context = new LSP.CompletionContext { TriggerCharacter = context.Trigger.Character.ToString(), TriggerKind = GetTriggerKind(context.Trigger) } }; var completionObject = await lspClient.RequestAsync(LSP.Methods.TextDocumentCompletion.ToLSRequest(), completionParams, context.CancellationToken).ConfigureAwait(false); if (completionObject == null) { return; } var completionList = ((JToken)completionObject).ToObject <RoslynCompletionItem[]>(); foreach (var item in completionList) { ImmutableArray <string> tags; if (item.Tags != null) { tags = item.Tags.AsImmutable(); } else { var glyph = ProtocolConversions.CompletionItemKindToGlyph(item.Kind); tags = GlyphTags.GetTags(glyph); } var properties = ImmutableDictionary.CreateBuilder <string, string>(); if (!string.IsNullOrEmpty(item.Detail)) { // The display text is encoded as TaggedText | value properties.Add("Description", $"Text|{item.Detail}"); } properties.Add("InsertionText", item.InsertText); properties.Add("ResolveData", JToken.FromObject(item).ToString()); var completionItem = CompletionItem.Create(item.Label, item.FilterText, item.SortText, properties: properties.ToImmutable(), tags: tags); context.AddItem(completionItem); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var cancellationToken = context.CancellationToken; var syntaxRoot = await context.Document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = syntaxRoot.FindNode(context.CompletionListSpan); var semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Check that we're inside a string literal which is a method argument if (!(node is ArgumentSyntax argNode) || !(argNode.Expression is LiteralExpressionSyntax literalNode) || !(argNode.Parent.Parent is InvocationExpressionSyntax invNode)) { return; } // Check that is is a method call if (!(semanticModel.GetSymbolInfo(invNode, cancellationToken).Symbol is IMethodSymbol methodSymbol)) { return; } // Check that it is a Dapper extension method call var sqlMapperSymbol = semanticModel.Compilation.GetTypeByMetadataName("Dapper.SqlMapper"); if (sqlMapperSymbol == null || !methodSymbol.ContainingType.Equals(sqlMapperSymbol) || methodSymbol.Name != "Query" || !methodSymbol.IsGenericMethod) { return; } // We don't want to show any other IntelliSense items except ours context.IsExclusive = true; // Get the string literal's value, considering the current position string text = literalNode.Token.ValueText; text = text.Substring(0, context.Position - literalNode.Token.SpanStart - 1); if (String.IsNullOrEmpty(text)) { context.AddItem(CompletionItem.Create("SELECT", tags: ImmutableArray.Create(WellKnownTags.Keyword))); } else { var parseResult = Parser.Parse(text); if (parseResult.Script.Batches.Count == 0 || parseResult.Script.Batches[0].Statements.Count == 0) { return; } var statement = parseResult.Script.Batches[0].Statements[0]; if (!(statement is SqlSelectStatement selectStatement)) { return; } if (!(selectStatement.SelectSpecification?.QueryExpression is SqlQuerySpecification query)) { return; } if (query.SelectClause.SelectExpressions.All(e => String.IsNullOrWhiteSpace(e.Sql))) { context.AddItem(CompletionItem.Create("TOP", tags: ImmutableArray.Create(WellKnownTags.Keyword))); context.AddItem(CompletionItem.Create("*", tags: ImmutableArray.Create(WellKnownTags.Keyword))); bool singleTable = methodSymbol.TypeArguments.Length == 1; foreach (var typePar in methodSymbol.TypeArguments) { foreach (var property in typePar.GetMembers() .OfType <IPropertySymbol>() .Where(p => p.DeclaredAccessibility.HasFlag(Accessibility.Public) && p.GetMethod != null)) { string propText = singleTable ? property.Name : $"{typePar.Name}.{property.Name}"; context.AddItem(CompletionItem.Create(propText, tags: ImmutableArray.Create(WellKnownTags.Property))); } } } } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { if (!context.Options.GetOption(RegularExpressionsOptions.ProvideRegexCompletions, context.Document.Project.Language)) { return; } if (context.Trigger.Kind != CompletionTriggerKind.Invoke && context.Trigger.Kind != CompletionTriggerKind.InvokeAndCommitIfUnique && context.Trigger.Kind != CompletionTriggerKind.Insertion) { return; } var position = context.Position; var(tree, stringToken) = await _language.TryGetTreeAndTokenAtPositionAsync( context.Document, position, context.CancellationToken).ConfigureAwait(false); if (tree == null || position <= stringToken.SpanStart || position >= stringToken.Span.End) { return; } var embeddedContext = new EmbeddedCompletionContext(_language, context, tree, stringToken); ProvideCompletions(embeddedContext); if (embeddedContext.Items.Count == 0) { return; } foreach (var embeddedItem in embeddedContext.Items) { var change = embeddedItem.Change; var textChange = change.TextChange; var properties = ImmutableDictionary.CreateBuilder <string, string>(); properties.Add(StartKey, textChange.Span.Start.ToString()); properties.Add(LengthKey, textChange.Span.Length.ToString()); properties.Add(NewTextKey, textChange.NewText); properties.Add(DescriptionKey, embeddedItem.FullDescription); properties.Add(EmbeddedLanguageCompletionProvider.EmbeddedProviderName, Name); if (change.NewPosition != null) { properties.Add(NewPositionKey, change.NewPosition.ToString()); } // Keep everything sorted in the order we just produced the items in. var sortText = context.Items.Count.ToString("0000"); context.AddItem(CompletionItem.Create( displayText: embeddedItem.DisplayText, inlineDescription: embeddedItem.InlineDescription, sortText: sortText, properties: properties.ToImmutable(), rules: s_rules)); } context.IsExclusive = true; }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken); if (syntaxRoot == null) { return; } var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var node = syntaxRoot.FindNode(context.CompletionListSpan); var argumentSyntaxNode = node.AncestorsAndSelf().OfType <ArgumentSyntax>().FirstOrDefault(); if (argumentSyntaxNode == null) { return; } var lambdaExpression = argumentSyntaxNode.Ancestors().OfType <LambdaExpressionSyntax>().FirstOrDefault(); if (lambdaExpression == null) { return; } var mockMethod = lambdaExpression.Ancestors().FirstOrDefault(x => semanticModel.GetSymbolInfo(x, context.CancellationToken).CandidateSymbols.Any(s => s.ContainingType.Name == "Mock" && s.ContainingAssembly.Name == "Moq")); if (mockMethod == null) { return; } var typingMethod = argumentSyntaxNode.Ancestors().OfType <InvocationExpressionSyntax>().First(); var calingMethod = semanticModel.GetSymbolInfo(typingMethod, context.CancellationToken); if (!(calingMethod.CandidateSymbols[0] is IMethodSymbol callingMethodSymbol)) { return; } var index = argumentSyntaxNode.Parent.ChildNodes().ToList().FindIndex(x => x.Equals(argumentSyntaxNode)); if (index < callingMethodSymbol.Parameters.Length) { context.AddItem(CompletionItem.Create(GetCompletionDisplayText(callingMethodSymbol.Parameters[index].Type), null, null, ImmutableDictionary.Create <string, string>(), ImmutableArray.Create(WellKnownTags.Method), CompletionItemRules.Create(formatOnCommit: true, matchPriority: MatchPriority.Preselect))); } if (index == 0) { context.AddItem(CompletionItem.Create(String.Join(", ", callingMethodSymbol.Parameters.Select(x => GetCompletionDisplayText(x.Type))), null, null, ImmutableDictionary.Create <string, string>(), ImmutableArray.Create(WellKnownTags.Method), CompletionItemRules.Create(formatOnCommit: true))); } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { try { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document .GetRequiredSyntaxTreeAsync(cancellationToken) .ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return; } var token = syntaxTree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (!token.IsKind(SyntaxKind.OpenBracketToken, SyntaxKind.CommaToken)) { return; } if ( token.Parent is not FunctionPointerUnmanagedCallingConventionListSyntax callingConventionList ) { return; } var contextPosition = token.SpanStart; var semanticModel = await document .ReuseExistingSpeculativeModelAsync(callingConventionList, cancellationToken) .ConfigureAwait(false); var completionItems = new HashSet <CompletionItem>(CompletionItemComparer.Instance); AddTypes(completionItems, contextPosition, semanticModel, cancellationToken); // Even if we didn't have types, there are four magic calling conventions recognized regardless. // We add these after doing the type lookup so if we had types we can show that instead foreach (var callingConvention in s_predefinedCallingConventions) { completionItems.Add( CompletionItem.Create( callingConvention, tags: GlyphTags.GetTags(Glyph.Keyword) ) ); } context.AddItems(completionItems); } catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e)) { // nop } }
void ICompletionSet.SetCompletionItems( IList <PresentationItem> completionItems, PresentationItem selectedItem, PresentationItem presetBuilder, bool suggestionMode, bool isSoftSelected, ImmutableArray <CompletionItemFilter> completionItemFilters, IReadOnlyDictionary <CompletionItem, string> completionItemToFilterText) { this._foregroundObject.AssertIsForeground(); VSCompletion selectedCompletionItem = null; // Initialize the completion map to a reasonable default initial size (+1 for the builder) _presentationItemMap = _presentationItemMap ?? new Dictionary <PresentationItem, VSCompletion>(completionItems.Count + 1); _completionItemToFilterText = completionItemToFilterText; try { this.WritableCompletionBuilders.BeginBulkOperation(); this.WritableCompletionBuilders.Clear(); #if DEV15 // If more than one filter was provided, then present it to the user. if (_filters == null && completionItemFilters.Length > 1) { _filters = completionItemFilters.Select(f => new IntellisenseFilter2(this, f, GetLanguage())) .ToArray(); } #endif var applicableToText = this.ApplicableTo.GetText(this.ApplicableTo.TextBuffer.CurrentSnapshot); var filteredSuggestionModeItem = new SimplePresentationItem( CompletionItem.Create( displayText: applicableToText, span: this.ApplicableTo.GetSpan(this.ApplicableTo.TextBuffer.CurrentSnapshot).Span.ToTextSpan()), selectedItem.CompletionService, isSuggestionModeItem: true); var showBuilder = suggestionMode || presetBuilder != null; var bestSuggestionModeItem = applicableToText.Length > 0 ? filteredSuggestionModeItem : presetBuilder ?? filteredSuggestionModeItem; if (showBuilder && bestSuggestionModeItem != null) { var suggestionModeCompletion = GetVSCompletion(bestSuggestionModeItem); this.WritableCompletionBuilders.Add(suggestionModeCompletion); if (selectedItem != null && selectedItem.IsSuggestionModeItem) { selectedCompletionItem = suggestionModeCompletion; } } } finally { this.WritableCompletionBuilders.EndBulkOperation(); } try { this.WritableCompletions.BeginBulkOperation(); this.WritableCompletions.Clear(); foreach (var item in completionItems) { var completionItem = GetVSCompletion(item); this.WritableCompletions.Add(completionItem); if (item == selectedItem) { selectedCompletionItem = completionItem; } } } finally { this.WritableCompletions.EndBulkOperation(); } this.SelectionStatus = new CompletionSelectionStatus( selectedCompletionItem, isSelected: !isSoftSelected, isUnique: selectedCompletionItem != null); }
public override async Task ProvideCompletionsAsync(CompletionContext completionContext) { if (!completionContext.Document.SupportsSemanticModel) { return; } var position = completionContext.Position; var document = completionContext.Document; var cancellationToken = completionContext.CancellationToken; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = completionContext.CompletionListSpan; var token = root.FindToken(span.Start); var node = token.Parent?.AncestorsAndSelf().FirstOrDefault(a => a.FullSpan.Contains(span)); if (node is LiteralExpressionSyntax literal && node?.Parent is AttributeArgumentSyntax argument && // TODO: we support only property syntax for completion in attributes, // since that's what XA has right now anyway, and we need to lookup the // [Category] attribute on the property. argument.NameEquals != null && node?.Parent?.Parent?.Parent is AttributeSyntax attribute) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var projectPath = string.IsNullOrEmpty(document.Project.FilePath) ? null : Path.GetDirectoryName(document.Project.FilePath); // From the attribute syntax, we'll get the constructor for the attribute var symbol = (semanticModel.GetSymbolInfo(attribute, cancellationToken).Symbol as IMethodSymbol)?.ContainingType; if (symbol?.ContainingNamespace.ToDisplayString() == "Android.App") { var name = argument.NameEquals.Name.ToString(); // First try explicit completion hint via Category var propertyInfo = symbol.GetMembers(name).FirstOrDefault() as IPropertySymbol; if (propertyInfo == null) { return; } string[] categories; var categoryAttr = propertyInfo.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == typeof(CategoryAttribute).FullName); if (categoryAttr == null) { // Apply default heuristics based on member name // Label/Description: @string // Icon/RoundIcon: @drawable; @mipmap // Theme: @style if (name == "Label" || name == "Description") { categories = new[] { "string" } } ; else if (name == "Icon" || name == "RoundIcon") { categories = new[] { "drawable", "mipmap" } } ; else if (name == "Theme") { categories = new[] { "style" } } ; else { return; } } else if (!categoryAttr.ConstructorArguments.IsDefaultOrEmpty) { categories = ((string)categoryAttr.ConstructorArguments[0].Value) .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim().TrimStart('@')) .ToArray(); } else { return; } var compilation = await document.Project.GetCompilationAsync(completionContext.CancellationToken); var resourceDesignerAttribute = compilation.Assembly.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::Android.Runtime.ResourceDesignerAttribute"); if (resourceDesignerAttribute != null && resourceDesignerAttribute.ConstructorArguments.Any()) { var resourceDesigner = compilation.GetTypeByMetadataName((string)resourceDesignerAttribute.ConstructorArguments.First().Value); if (resourceDesigner != null) { foreach (var category in categories) { var resourceSymbol = resourceDesigner.GetTypeMembers().FirstOrDefault(x => x.Name.Equals(category, StringComparison.OrdinalIgnoreCase)); if (resourceSymbol != null) { foreach (var member in resourceSymbol.GetMembers().Where(x => x.Kind == SymbolKind.Field)) { completionContext.AddItem(CompletionItem.Create( displayText: member.Name, displayTextPrefix: $"@{category}/", sortText: $"@{category}/{member.Name}", properties: ImmutableDictionary.Create <string, string>() .Add("Summary", member.GetDocumentationCommentXml()) // Add the starting quote char to start position .Add("Start", (node.Span.Start + 1).ToString()) // Remove the two quote characters .Add("Length", (node.Span.Length - 2).ToString()), tags: ImmutableArray.Create(WellKnownTags.Constant, "Xamarin"), rules: CompletionItemRules.Default)); } } } } } } } await Task.CompletedTask; }
void AddDefaultSuggestion(string suggestion) { this._context.AddItem(CompletionItem.Create(suggestion, rules: _defaultCompletions)); }
public static dynamic CompileRos(SourceInfo sourceInfo) { var usings = new List <string>(); var allusingsInCode = sourceInfo.SourceCode.Split(new string[] { "using " }, StringSplitOptions.None); foreach (var item in allusingsInCode) { if (!String.IsNullOrWhiteSpace(item)) { usings.Add(item.Split(';')[0]); } } List <Assembly> assemblies = new List <Assembly> { Assembly.Load("Microsoft.CodeAnalysis"), Assembly.Load("Microsoft.CodeAnalysis.CSharp"), Assembly.Load("Microsoft.CodeAnalysis.Features"), Assembly.Load("Microsoft.CodeAnalysis.CSharp.Features"), }; var assembliesList = DownloadNugetPackages.LoadPackages(sourceInfo.Nuget); foreach (var item in assembliesList) { var fname = item.FullName.Split(',')[0]; if (assemblies.Where(x => x.FullName.Split(',')[0] == fname).FirstOrDefault() == null) { try { var asm = item.FullName.Split(',')[0]; var loadAssembly = Assembly.Load(asm); assemblies.Add(loadAssembly); } catch (Exception) { //assemblies.Add(item); } } } var assembliest = AppDomain.CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic && File.Exists(a.Location)); //MefHostServices.DefaultAssemblies.AddRange (assembliest); var partTypes = MefHostServices.DefaultAssemblies.Concat(assemblies) .Distinct()? .SelectMany(x => x?.GetTypes())? .ToArray(); var compositionContext = new ContainerConfiguration() .WithParts(partTypes) //.WithAssemblies(assemblies) //.WithAssemblies(assembliest) .CreateContainer(); var host = MefHostServices.Create(compositionContext); var workspace = new AdhocWorkspace(host); var scriptCode = sourceInfo.SourceCode;// "Guid.N"; var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: usings); if (_ref == null || _ref.Length == 0) { //.GroupBy(a => a.GetName().Name) //.Select(grp => // grp.First(y => y.GetName().Version == grp.Max(x => x.GetName().Version))) //.Select(a => MetadataReference.CreateFromFile(a.Location)); MetadataReference[] _refs2 = assembliest .Select(asm => MetadataReference.CreateFromFile(asm.Location)) .ToArray(); MetadataReference[] _refs = assembliesList .Select(asm => MetadataReference.CreateFromFile(asm.Location)) .ToArray(); _ref = new MetadataReference[0]; try { try { foreach (var item in DependencyContext.Default.CompileLibraries) { try { var arr = item.ResolveReferencePaths().Select(asm => MetadataReference.CreateFromFile(asm))? .ToArray(); _ref = _ref.Concatenate(arr); } catch (Exception) { } } } catch (Exception) { } } catch (Exception) { } _ref = _ref.Concatenate(_refs); _ref = _ref.Concatenate(_refs2); } if (_ref != null && _ref.Length > 0) { _ref = _ref.Concatenate(new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var scriptProjectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Script", "Script", LanguageNames.CSharp, isSubmission: true) .WithMetadataReferences(_ref) .WithCompilationOptions(compilationOptions); var scriptProject = workspace.AddProject(scriptProjectInfo); var scriptDocumentInfo = DocumentInfo.Create( DocumentId.CreateNewId(scriptProject.Id), "Script", sourceCodeKind: SourceCodeKind.Script, loader: TextLoader.From(TextAndVersion.Create(SourceText.From(scriptCode), VersionStamp.Create()))); var scriptDocument = workspace.AddDocument(scriptDocumentInfo); // cursor position is at the end var position = sourceInfo.LineNumberOffsetFromTemplate;// scriptCode.Length - 1; var completionService = CompletionService.GetService(scriptDocument); var results = completionService.GetCompletionsAsync(scriptDocument, position).Result; if (results == null && sourceInfo.LineNumberOffsetFromTemplate < sourceInfo.SourceCode.Length) { sourceInfo.LineNumberOffsetFromTemplate++; CompileRos(sourceInfo); } if (sourceInfo.SourceCode[sourceInfo.LineNumberOffsetFromTemplate - 1].ToString() == "(") { sourceInfo.LineNumberOffsetFromTemplate--; //CompileRos(sourceInfo); results = completionService.GetCompletionsAsync(scriptDocument, sourceInfo.LineNumberOffsetFromTemplate).Result; } //Method parameters List <string> overloads = GetMethodParams(scriptCode, position); if (overloads != null && overloads.Count > 0) { ImmutableArray <CompletionItem> .Builder builder = ImmutableArray.CreateBuilder <CompletionItem>(); foreach (var item in overloads) { string DisplayText = item; string insertText = item.Split('(')[1].Split(')')[0]; CompletionItem ci = CompletionItem.Create(insertText, insertText, insertText); builder.Add(ci); } if (builder.Count > 0) { ImmutableArray <CompletionItem> itemlist = builder.ToImmutable(); return(CompletionList.Create(new Microsoft.CodeAnalysis.Text.TextSpan(), itemlist)); } } return(results); } return(null); }
public static dynamic CompileRos2(SourceInfo sourceInfo) { List <Assembly> assemblies = new List <Assembly> { Assembly.Load("Microsoft.CodeAnalysis"), Assembly.Load("Microsoft.CodeAnalysis.CSharp"), Assembly.Load("Microsoft.CodeAnalysis.Features"), Assembly.Load("Microsoft.CodeAnalysis.CSharp.Features"), }; var assembliesList = DownloadNugetPackages.LoadPackages(sourceInfo.Nuget); foreach (var item in assembliesList) { var fname = item.FullName.Split(',')[0]; if (assemblies.Where(x => x.FullName.Split(',')[0] == fname).FirstOrDefault() == null) { var loadAssembly = Assembly.Load(item.FullName.Split(',')[0]); assemblies.Add(loadAssembly); } } var partTypes = MefHostServices.DefaultAssemblies.Concat(assemblies) .Distinct() .SelectMany(x => x.GetTypes()) .ToArray(); var compositionContext = new ContainerConfiguration() .WithParts(partTypes) //.WithAssemblies(assemblies) .CreateContainer(); var host = MefHostServices.Create(compositionContext); var workspace = new AdhocWorkspace(host); var scriptCode = sourceInfo.SourceCode;// "Guid.N"; var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); var usings = new List <string>(); var allusingsInCode = sourceInfo.SourceCode.Split(new string[] { "using " }, StringSplitOptions.None); foreach (var item in allusingsInCode) { if (!String.IsNullOrWhiteSpace(item)) { usings.Add(item.Split(';')[0]); } } var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: usings); MetadataReference[] _ref = DependencyContext.Default.CompileLibraries .First(cl => cl.Name == "mssqlrestapi") .ResolveReferencePaths() .Select(asm => MetadataReference.CreateFromFile(asm)) .ToArray(); MetadataReference[] _refs = assembliesList .Select(asm => MetadataReference.CreateFromFile(asm.Location)) .ToArray(); MetadataReference[] newArray = new MetadataReference[_ref.Length + _refs.Length]; Array.Copy(_ref, newArray, _ref.Length); Array.Copy(_refs, 0, newArray, _ref.Length, _refs.Length); //assembliesList //IMethodSymbol methodWithGenericTypeArgsSymbol = simpleClassToAnalyze.GetMembers("MySimpleMethod").FirstOrDefault() as IMethodSymbol; //var genericMethodSignature = methodWithGenericTypeArgsSymbol.Parameters; var scriptProjectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Script", "Script", LanguageNames.CSharp, isSubmission: true) .WithMetadataReferences(newArray) .WithCompilationOptions(compilationOptions); // without .net asseblies // .WithMetadataReferences(new[] // { // MetadataReference.CreateFromFile(typeof(object).Assembly.Location) // }) var scriptProject = workspace.AddProject(scriptProjectInfo); var scriptDocumentInfo = DocumentInfo.Create( DocumentId.CreateNewId(scriptProject.Id), "Script", sourceCodeKind: SourceCodeKind.Script, loader: TextLoader.From(TextAndVersion.Create(SourceText.From(scriptCode), VersionStamp.Create()))); var scriptDocument = workspace.AddDocument(scriptDocumentInfo); // cursor position is at the end var position = sourceInfo.LineNumberOffsetFromTemplate;// scriptCode.Length - 1; var completionService = CompletionService.GetService(scriptDocument); var results = completionService.GetCompletionsAsync(scriptDocument, position).Result; if (results == null && sourceInfo.LineNumberOffsetFromTemplate < sourceInfo.SourceCode.Length) { sourceInfo.LineNumberOffsetFromTemplate++; CompileRos2(sourceInfo); } //Method parameters List <string> overloads = GetMethodParams(scriptCode, position); if (overloads != null && overloads.Count > 0) { ImmutableArray <CompletionItem> .Builder builder = ImmutableArray.CreateBuilder <CompletionItem>(); foreach (var item in overloads) { string DisplayText = item; string insertText = item.Split('(')[1].Split(')')[0]; CompletionItem ci = CompletionItem.Create(insertText, insertText, insertText); builder.Add(ci); } if (builder.Count > 0) { ImmutableArray <CompletionItem> itemlist = builder.ToImmutable(); return(CompletionList.Create(new Microsoft.CodeAnalysis.Text.TextSpan(), itemlist)); } } return(results);// JsonConvert.SerializeObject(results); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentTypeArgumentList(syntaxRoot, context.Position); if (!tokenAtCursor.IsKind(SyntaxKind.GreaterThanToken)) { return; } var typeArgumentList = tokenAtCursor.Parent as TypeArgumentListSyntax; // We are aiming Mock<T>, so can do shortcut exit here for mismatches if (typeArgumentList.Arguments.Count != 1) { return; } var genericName = typeArgumentList?.Parent as GenericNameSyntax; // TODO: Yuk! Sometimes additional parent appears. var memberSyntax = genericName?.Parent as IncompleteMemberSyntax ?? genericName?.Parent?.Parent as IncompleteMemberSyntax; var classDeclaration = memberSyntax?.Parent as ClassDeclarationSyntax; // Ignore if not a field/method declaration if (classDeclaration == null) { return; } var typeInfo = semanticModel.GetTypeInfo(genericName); var type = typeInfo.Type as INamedTypeSymbol; if (type == null || type.ConstructedFrom == null) { return; } if (type.ConstructedFrom.ToString() != "Moq.Mock<T>") { return; } var mockedType = typeArgumentList.Arguments[0]; var mockedTypeInfo = semanticModel.GetTypeInfo(mockedType); if (mockedTypeInfo.Type == null) { return; } var mockedTypeName = mockedTypeInfo.Type.Name; if (mockedTypeName.Length > 1 && mockedTypeName[0] == 'I' && Char.IsUpper(mockedTypeName[1])) // ISomething { mockedTypeName = mockedTypeName.Substring(1); } context.AddItem(CompletionItem.Create(mockedTypeName.Substring(0, 1).ToLower() + mockedTypeName.Substring(1) + "Mock", rules: _preselectCompletionRules)); } catch (Exception) { // ignore } }
public override async Task ProvideCompletionsAsync(CompletionContext context) { SyntaxNode?syntaxNode = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); if (!(syntaxNode?.FindNode(context.CompletionListSpan) is ExpressionStatementSyntax expressionStatementSyntax)) { return; } if (!(expressionStatementSyntax.Expression is MemberAccessExpressionSyntax syntax)) { return; } if (!(await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false) is { } model)) { return; } ITypeSymbol?typeSymbol = model.GetSymbolInfo(syntax.Expression).Symbol switch { IMethodSymbol s => s.ReturnType, ILocalSymbol s => s.Type, IPropertySymbol s => s.Type, IFieldSymbol s => s.Type, IParameterSymbol s => s.Type, _ => null }; if (typeSymbol == null) { return; } foreach (IEventSymbol ev in typeSymbol.GetMembersOfType <IEventSymbol>()) { if (!(ev.Type is INamedTypeSymbol namedTypeSymbol)) { continue; } if (namedTypeSymbol.DelegateInvokeMethod == null) { continue; } List <ITypeSymbol>?typeArguments = namedTypeSymbol.DelegateInvokeMethod.Parameters.Select(m => m.Type).ToList(); string fullType = namedTypeSymbol.ToDisplayString(); List <string>?taggedTexts = new List <string>() { WellKnownTags.ExtensionMethod }; switch (typeArguments.Count) { case 0: taggedTexts.Add(TextTags.Class); taggedTexts.Add(fullType); break; case 1: taggedTexts.Add(typeArguments.First().IsValueType ? TextTags.Struct : TextTags.Class); taggedTexts.Add(typeArguments.First().ToDisplayString()); break; default: taggedTexts.Add(TextTags.Text); taggedTexts.Add("("); foreach ((ITypeSymbol? type, int i) in typeArguments.Select((type, i) => (type, i))) { taggedTexts.Add(typeArguments.First().IsValueType ? TextTags.Struct : TextTags.Class); taggedTexts.Add(type.ToDisplayString()); taggedTexts.Add(TextTags.Parameter); taggedTexts.Add($" Item{i + 1}"); taggedTexts.Add(TextTags.Text); taggedTexts.Add(", "); } taggedTexts.RemoveAt(taggedTexts.Count - 1); taggedTexts.RemoveAt(taggedTexts.Count - 1); taggedTexts.Add(TextTags.Text); taggedTexts.Add(") "); taggedTexts.Add(TextTags.Class); taggedTexts.Add($"RxGeneratedMethods."); taggedTexts.Add(TextTags.Method); taggedTexts.Add($"Rx{ev.Name}()"); break; } CompletionItem item = CompletionItem.Create($"Rx{ev.Name}", tags: ImmutableArray.Create(taggedTexts.ToArray())); context.AddItem(item); } }
void AddSuggestion(string suggestion) { this._context.AddItem(CompletionItem.Create(suggestion, rules: _preselectCompletions)); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentArgumentListSyntaxToken(syntaxRoot, context.Position); if (!tokenAtCursor.IsKind(SyntaxKind.OpenParenToken) && !tokenAtCursor.IsKind(SyntaxKind.CommaToken)) { return; } var argumentList = tokenAtCursor.Parent as ArgumentListSyntax; var allCommaTokens = argumentList.ChildTokens().Where(t => t.IsKind(SyntaxKind.CommaToken)).ToList(); int argumentIdx = tokenAtCursor.IsKind(SyntaxKind.CommaToken) ? allCommaTokens.IndexOf(tokenAtCursor) + 1 : 0; var constructorCall = argumentList.Parent as ObjectCreationExpressionSyntax; var matchingConstructorSymbols = Helpers.GetAllMatchingSymbols <IMethodSymbol>(semanticModel, constructorCall); if (matchingConstructorSymbols == null) { return; } var matchingSymbols = new HashSet <ISymbol>(); var symbols = semanticModel.LookupSymbols(context.Position); foreach (var symbol in symbols) { INamedTypeSymbol symbolType; if (symbol is IFieldSymbol) { var fieldSymbol = symbol as IFieldSymbol; symbolType = fieldSymbol?.Type as INamedTypeSymbol; } else if (symbol is ILocalSymbol) { var localSymbol = symbol as ILocalSymbol; symbolType = localSymbol.Type as INamedTypeSymbol; } else { continue; } if (symbolType == null || symbolType.ConstructedFrom == null) { continue; } if (symbolType.ConstructedFrom.ToString() != "Moq.Mock<T>" || symbolType.TypeArguments.Length != 1) { continue; } var typeArgument = symbolType.TypeArguments[0]; foreach (var methodSymbol in matchingConstructorSymbols.Where(m => m.Parameters.Length > argumentIdx)) { if (methodSymbol.Parameters[argumentIdx].Type.ToString() == typeArgument.ToString()) { matchingSymbols.Add(symbol); } } } foreach (var symbol in matchingSymbols) { context.AddItem(CompletionItem.Create(symbol.Name + ".Object", rules: _preselectCompletionRules)); } } catch (Exception) { // ignore } }
public void SetCompletionItems( IList <PresentationItem> completionItems, PresentationItem selectedItem, PresentationItem presetBuilder, bool suggestionMode, bool isSoftSelected, ImmutableArray <CompletionItemFilter> completionItemFilters, IReadOnlyDictionary <CompletionItem, string> completionItemToFilterText) { this.AssertIsForeground(); VSCompletion selectedCompletionItem = null; // Initialize the completion map to a reasonable default initial size (+1 for the builder) PresentationItemMap = PresentationItemMap ?? new Dictionary <PresentationItem, VSCompletion>(completionItems.Count + 1); CompletionItemToFilterText = completionItemToFilterText; try { VsCompletionSet.WritableCompletionBuilders.BeginBulkOperation(); VsCompletionSet.WritableCompletionBuilders.Clear(); this.SetupFilters(completionItemFilters); var applicableToText = VsCompletionSet.ApplicableTo.GetText( VsCompletionSet.ApplicableTo.TextBuffer.CurrentSnapshot); SimplePresentationItem filteredSuggestionModeItem = null; if (selectedItem != null) { filteredSuggestionModeItem = new SimplePresentationItem( CompletionItem.Create( displayText: applicableToText, span: VsCompletionSet.ApplicableTo.GetSpan( VsCompletionSet.ApplicableTo.TextBuffer.CurrentSnapshot).Span.ToTextSpan()), selectedItem.CompletionService, isSuggestionModeItem: true); } var showBuilder = suggestionMode || presetBuilder != null; var bestSuggestionModeItem = applicableToText.Length > 0 ? filteredSuggestionModeItem : presetBuilder ?? filteredSuggestionModeItem; if (showBuilder && bestSuggestionModeItem != null) { var suggestionModeCompletion = GetVSCompletion(bestSuggestionModeItem); VsCompletionSet.WritableCompletionBuilders.Add(suggestionModeCompletion); if (selectedItem != null && selectedItem.IsSuggestionModeItem) { selectedCompletionItem = suggestionModeCompletion; } } } finally { VsCompletionSet.WritableCompletionBuilders.EndBulkOperation(); } try { VsCompletionSet.WritableCompletions.BeginBulkOperation(); VsCompletionSet.WritableCompletions.Clear(); foreach (var item in completionItems) { var completionItem = GetVSCompletion(item); VsCompletionSet.WritableCompletions.Add(completionItem); if (item == selectedItem) { selectedCompletionItem = completionItem; } } } finally { VsCompletionSet.WritableCompletions.EndBulkOperation(); } VsCompletionSet.SelectionStatus = new CompletionSelectionStatus( selectedCompletionItem, isSelected: !isSoftSelected, isUnique: selectedCompletionItem != null); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { // wrap it in try catch, because exception for some reason sometimes crash entire VisualStudio try { if (!context.Document.SupportsSemanticModel) { return; } var syntaxRoot = await context.Document.GetSyntaxRootAsync(); var semanticModel = await context.Document.GetSemanticModelAsync(); var tokenAtCursor = Helpers.GetCurrentArgumentListSyntaxToken(syntaxRoot, context.Position); if (tokenAtCursor.Kind() == SyntaxKind.None) { return; } var mockedMethodArgumentList = tokenAtCursor.Parent as ArgumentListSyntax; var mockedMethodInvocation = mockedMethodArgumentList?.Parent as InvocationExpressionSyntax; var setupMethodLambda = mockedMethodInvocation?.Parent as LambdaExpressionSyntax; var setupMethodArgument = setupMethodLambda?.Parent as ArgumentSyntax; var setupMethodArgumentList = setupMethodArgument?.Parent as ArgumentListSyntax; var setupMethodInvocation = setupMethodArgumentList?.Parent as InvocationExpressionSyntax; if (Helpers.IsMoqSetupMethod(semanticModel, setupMethodInvocation)) { var matchingMockedMethods = Helpers.GetAllMatchingMockedMethodSymbolsFromSetupMethodInvocation(semanticModel, setupMethodInvocation); // TODO Narrow the list of matching signatures if some arguments are already provided foreach (IMethodSymbol matchingMockedMethodSymbol in matchingMockedMethods.Where(m => m.Parameters.Any())) { // We are at first argument if (tokenAtCursor.IsKind(SyntaxKind.OpenParenToken)) { // Generate It.IsAny<>() for the whole signature if we are within first argument var fullMethodHelper = string.Join(", ", matchingMockedMethodSymbol.Parameters.Select(p => "It.IsAny<" + p.Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()")); context.AddItem(CompletionItem.Create(fullMethodHelper, rules: _preselectCompletionRules)); // There are more than one argument so suggest completion for first argument only too if (matchingMockedMethodSymbol.Parameters.Length > 1) { var oneArgumentHelper = "It.IsAny<" + matchingMockedMethodSymbol.Parameters[0].Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()"; context.AddItem(CompletionItem.Create(oneArgumentHelper, rules: _standardCompletionRules)); } } // We are at second+ argument else { // Generate It.IsAny<>() for single argument var allCommaTokens = mockedMethodArgumentList.ChildTokens().Where(t => t.IsKind(SyntaxKind.CommaToken)).ToList(); int paramIdx = allCommaTokens.IndexOf(tokenAtCursor) + 1; if (matchingMockedMethodSymbol.Parameters.Length > paramIdx) { var oneArgumentHelper = "It.IsAny<" + matchingMockedMethodSymbol.Parameters[paramIdx].Type.ToMinimalDisplayString(semanticModel, mockedMethodArgumentList.SpanStart) + ">()"; context.AddItem(CompletionItem.Create(oneArgumentHelper, rules: _standardCompletionRules)); } } } } } catch (Exception) { // ignore } }
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)); } } } }
private static CompletionItem CreateDefaultSuggestionModeItem(TextSpan defaultTrackingSpanInSubjectBuffer) { return(CompletionItem.Create(displayText: "", span: defaultTrackingSpanInSubjectBuffer)); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var cancellationToken = context.CancellationToken; // Получаем семантическую модель (она понадобится для работы с типами и методами) var semanticModel = await context.Document .GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Находим синтаксическую ноду, внутри который был вызван IntelliSense var syntaxRoot = await context.Document .GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = syntaxRoot.FindNode(context.CompletionListSpan); // Проверяем, что мы внутри строкового литерала, который к тому же является аргументом вызова метода if (!(node is ArgumentSyntax argNode) || !(argNode.Expression is LiteralExpressionSyntax literalNode) || !(argNode.Parent.Parent is InvocationExpressionSyntax invNode)) { return; } // Получаем семантическую информацию о вызываемом методе var symbolInfo = semanticModel.GetSymbolInfo(invNode, cancellationToken); var methodSymbol = (symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault()) as IMethodSymbol; if (methodSymbol == null) { return; } // Проверяем, что это действительно метод Dapper var sqlMapperSymbol = semanticModel.Compilation.GetTypeByMetadataName("Dapper.SqlMapper"); if (sqlMapperSymbol == null || !methodSymbol.ContainingType.Equals(sqlMapperSymbol) || methodSymbol.Name != "Query" || !methodSymbol.IsGenericMethod) { return; } // Даём системе понять, что мы хотим показывать только наши completion items, и никакие другие // (не использовать другие completion provider'ы, кроме текущего) context.IsExclusive = true; // Получаем строку от начала строкового литерала до курсора ввода string text = literalNode.Token.ValueText; int selectedLength = context.Position - literalNode.Token.SpanStart - 1; if (selectedLength < text.Length) { text = text.Substring(0, selectedLength); } // Собираем информацию о всех свойствах DTO-классов, используемых в запросе var properties = methodSymbol.TypeArguments.SelectMany(t => t .GetMembers() .OfType <IPropertySymbol>() .Where(p => p.DeclaredAccessibility.HasFlag(Accessibility.Public) && p.GetMethod != null)).ToArray(); // Определяем, в какой части SQL-запроса мы сейчас находимся, и что же нужно показывать пользователю if (String.IsNullOrEmpty(text)) { // Добавляем новый пункт в IntelliSense... context.AddItem(CompletionItem.Create("SELECT") // ...показывая его, как ключевое слово языка (соответствующая иконка) .AddTag(WellKnownTags.Keyword)); } else { if (text.StartsWith("SELECT ", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" FROM ", StringComparison.OrdinalIgnoreCase)) { if (text.Equals("SELECT ", StringComparison.OrdinalIgnoreCase)) { context.AddItem(CompletionItem.Create("DISTINCT", sortText: "K DISTINCT") .AddTag(WellKnownTags.Keyword)); context.AddItem(CompletionItem.Create("TOP", sortText: "K TOP") .AddTag(WellKnownTags.Keyword)); } if (!text.EndsWith(" TOP ", StringComparison.OrdinalIgnoreCase)) { context.AddItem(CompletionItem.Create("*", sortText: "K *") .AddTag(WellKnownTags.Keyword)); bool singleTable = methodSymbol.TypeArguments.Length == 1; foreach (var property in properties) { string propText = singleTable ? property.Name : $"{property.ContainingType.Name}.{property.Name}"; context.AddItem(CompletionItem.Create(propText, sortText: $"P {propText}") .AddTag(WellKnownTags.Property) // Добавляем XML-комментарий от свойства DTO-класса как метаинформацию .AddProperty("comment", property.GetDocumentationCommentXml())); } } if (text.EndsWith(" * ", StringComparison.OrdinalIgnoreCase) || properties.Any(p => text.EndsWith(p.Name + " "))) { context.AddItem(CompletionItem.Create("FROM", sortText: "K FROM") .AddTag(WellKnownTags.Keyword)); } } else if (text.EndsWith(" FROM ", StringComparison.OrdinalIgnoreCase)) { foreach (var typePar in methodSymbol.TypeArguments) { context.AddItem(CompletionItem.Create(typePar.Name) .AddTag(WellKnownTags.Class) // Добавляем XML-комментарий от DTO-класса как метаинформацию .AddProperty("comment", typePar.GetDocumentationCommentXml())); } } } }
private static CompletionItem CreateDefaultSuggestionModeItem() => CompletionItem.Create(displayText: "");
private static CompletionItem CreateDefaultSuggestionModeItem() { return(CompletionItem.Create(displayText: "")); }