public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return; } var textChangeSpan = GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, ItemRules.Instance); var referenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver; // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolvers. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) ImmutableArray<string> searchPaths; RuntimeMetadataReferenceResolver rtResolver; WorkspaceMetadataFileReferenceResolver workspaceResolver; if ((rtResolver = referenceResolver as RuntimeMetadataReferenceResolver) != null) { searchPaths = rtResolver.PathResolver.SearchPaths; } else if ((workspaceResolver = referenceResolver as WorkspaceMetadataFileReferenceResolver) != null) { searchPaths = workspaceResolver.PathResolver.SearchPaths; } else { return; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, new CurrentWorkingDirectoryDiscoveryService(Directory.GetCurrentDirectory()), Microsoft.CodeAnalysis.Glyph.OpenFolder, Microsoft.CodeAnalysis.Glyph.Assembly, searchPaths, new[] { ".dll", ".exe" }, path => path.Contains(","), ItemRules.Instance); var pathThroughLastSlash = GetPathThroughLastSlash(stringLiteral, position); var documentPath = document.Project.IsSubmission ? null : document.FilePath; context.AddItems(gacHelper.GetItems(pathThroughLastSlash, documentPath)); context.AddItems(fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
private ImmutableArray<CompletionItem> GetItems(SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var line = text.Lines.GetLineFromPosition(position); var lineText = text.ToString(TextSpan.FromBounds(line.Start, position)); var match = s_directiveRegex.Match(lineText); if (!match.Success) { return ImmutableArray<CompletionItem>.Empty; } var quotedPathGroup = match.Groups[1]; var quotedPath = quotedPathGroup.Value; var endsWithQuote = PathCompletionUtilities.EndsWithQuote(quotedPath); if (endsWithQuote && (position >= line.Start + match.Length)) { return ImmutableArray<CompletionItem>.Empty; } var buffer = text.Container.GetTextBuffer(); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { return ImmutableArray<CompletionItem>.Empty; } var fileSystem = CurrentWorkingDirectoryDiscoveryService.GetService(snapshot); var searchPaths = ImmutableArray.Create(fileSystem.CurrentDirectory); var helper = new FileSystemCompletionHelper( this, GetTextChangeSpan(text, position, quotedPathGroup), fileSystem, Glyph.OpenFolder, Glyph.CSharpFile, searchPaths: searchPaths, allowableExtensions: new[] { ".csx" }, itemRules: ItemRules.Instance); var pathThroughLastSlash = this.GetPathThroughLastSlash(text, position, quotedPathGroup); return helper.GetItems(pathThroughLastSlash, documentPath: null); }
public override async Task ProvideCompletionsAsync(CompletionContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return; } var textChangeSpan = this.GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, itemRules: s_rules); var text = await document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { // Passing null to GetFileSystemDiscoveryService raises an exception. // Instead, return here since there is no longer snapshot for this document. return; } var referenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver; // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolvers. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) ImmutableArray<string> searchPaths; RuntimeMetadataReferenceResolver rtResolver; WorkspaceMetadataFileReferenceResolver workspaceResolver; if ((rtResolver = referenceResolver as RuntimeMetadataReferenceResolver) != null) { searchPaths = rtResolver.PathResolver.SearchPaths; } else if ((workspaceResolver = referenceResolver as WorkspaceMetadataFileReferenceResolver) != null) { searchPaths = workspaceResolver.PathResolver.SearchPaths; } else { return; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, GetFileSystemDiscoveryService(snapshot), Glyph.OpenFolder, Glyph.Assembly, searchPaths: searchPaths, allowableExtensions: new[] { ".dll", ".exe" }, exclude: path => path.Contains(","), itemRules: s_rules); var pathThroughLastSlash = GetPathThroughLastSlash(stringLiteral, position); var documentPath = document.Project.IsSubmission ? null : document.FilePath; context.AddItems(gacHelper.GetItems(pathThroughLastSlash, documentPath)); context.AddItems(fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
private ImmutableArray<CompletionItem> GetItems(SourceText text, Document document, int position, CompletionTrigger triggerInfo, CancellationToken cancellationToken) { var line = text.Lines.GetLineFromPosition(position); var lineText = text.ToString(TextSpan.FromBounds(line.Start, position)); var match = s_directiveRegex.Match(lineText); if (!match.Success) { return ImmutableArray<CompletionItem>.Empty; } var quotedPathGroup = match.Groups[1]; var quotedPath = quotedPathGroup.Value; var endsWithQuote = PathCompletionUtilities.EndsWithQuote(quotedPath); if (endsWithQuote && (position >= line.Start + match.Length)) { return ImmutableArray<CompletionItem>.Empty; } var buffer = text.Container.GetTextBuffer(); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { return ImmutableArray<CompletionItem>.Empty; } var fileSystem = CurrentWorkingDirectoryDiscoveryService.GetService(snapshot); // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolver. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) var searchPaths = (document.Project.CompilationOptions.SourceReferenceResolver as SourceFileResolver)?.SearchPaths ?? ImmutableArray<string>.Empty; var helper = new FileSystemCompletionHelper( this, GetTextChangeSpan(text, position, quotedPathGroup), fileSystem, Glyph.OpenFolder, Glyph.CSharpFile, searchPaths: searchPaths, allowableExtensions: new[] { ".csx" }, itemRules: s_rules); var pathThroughLastSlash = this.GetPathThroughLastSlash(text, position, quotedPathGroup); return helper.GetItems(pathThroughLastSlash, documentPath: null); }