public IEnumerable <IRFunctionQuickInfo> GetQuickInfosAsync(IRIntellisenseContext context, Action <IEnumerable <IRFunctionQuickInfo> > callback) { // Get function name from the AST. We don't use signature support here since // when caret or mouse is inside function arguments such as in abc(de|f(x)) // it gives information of the outer function since signature is about help // on the function arguments. var functionName = context.AstRoot.GetFunctionName(context.Position, out var fc, out var fv); if (!string.IsNullOrEmpty(functionName) && fc != null) { var signatureInfo = context.AstRoot.GetSignatureInfo(fc, fv, fc.OpenBrace.End); var applicableRange = context.EditorBuffer.CurrentSnapshot.CreateTrackingRange(fv); var sigs = GetSignaturesAsync(signatureInfo, context, null); if (sigs != null) { return(MakeQuickInfos(sigs, applicableRange)); } if (callback != null) { GetSignaturesAsync(signatureInfo, context, signatures => callback(MakeQuickInfos(signatures, applicableRange))); } } else { callback?.Invoke(Enumerable.Empty <IRFunctionQuickInfo>()); } return(null); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context) { var completions = new List <ICompletionEntry>(); var infoSource = _snippetInformationSource?.InformationSource; var packages = GetPackages(context).ToList(); var packageName = packages.Count == 1 ? packages[0].Name : null; // Get list of functions in the package foreach (var pkg in packages) { Debug.Assert(pkg != null); var functions = pkg.Functions; if (functions == null) { continue; } foreach (var function in functions) { // Snippets are suppressed if user typed namespace if (!context.IsCaretInNamespace() && infoSource != null) { if (infoSource.IsSnippet(function.Name)) { continue; } } var glyph = function.ItemType == NamedItemType.Constant ? _constantGlyph : _functionGlyph; var completion = new RFunctionCompletionEntry(function.Name, function.Name.BacktickName(), function.Description, glyph, packageName, _functionIndex, context.Session); completions.Add(completion); } } return(completions); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context) { var completions = new List <ICompletionEntry>(); var start = DateTime.Now; _variablesProvider.Initialize(); var names = GetFieldProvidingVariableNames(context); foreach (var variableName in names) { var members = _variablesProvider.GetMembers(variableName, 200); foreach (var v in members) { Debug.Assert(v != null); if (v.Name.Length > 0 && v.Name[0] != '[') { var glyph = v.ItemType == NamedItemType.Variable ? _variableGlyph : _functionGlyph; var completion = new EditorCompletionEntry(v.Name, v.Name.BacktickName(), v.Description, glyph); completions.Add(completion); } } } Debug.WriteLine("Variable members fetch: " + (DateTime.Now - start).TotalMilliseconds); return(completions); }
public async Task <IReadOnlyCollection <ICompletionEntry> > GetEntriesAsync(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); var directory = _enteredDirectory; await _task; try { // If directory is set, then the async task did complete if (!string.IsNullOrEmpty(_rootDirectory)) { if (_mode == Mode.WorkingDirectory) { directory = Path.Combine(_rootDirectory, _enteredDirectory); } else if (_mode == Mode.UserDirectory) { var subDirectory = _enteredDirectory.Length > 1 ? _enteredDirectory.Substring(2) : _enteredDirectory; directory = Path.Combine(_rootDirectory, subDirectory); } } } catch (ArgumentException) { } try { if (!string.IsNullOrEmpty(directory)) { IEnumerable <ICompletionEntry> entries; entries = GetLocalDirectoryItems(directory); completions.AddRange(entries); } } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (ArgumentException) { } catch (TimeoutException) { } return(completions); }
public Task <IReadOnlyCollection <ICompletionEntry> > GetEntriesAsync(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); if (!context.IsCaretInNamespace()) { var infoSource = _snippetInformationSource?.InformationSource; var keyWordGlyph = _imageService.GetImage(ImageType.Keyword); // Union with constants like TRUE and other common things var keywords = Keywords.KeywordList.Concat(Logicals.LogicalsList).Concat(Constants.ConstantsList); foreach (var keyword in keywords) { var isSnippet = infoSource?.IsSnippet(keyword); if (!isSnippet.HasValue || !isSnippet.Value) { completions.Add(new EditorCompletionEntry(keyword, keyword, string.Empty, keyWordGlyph)); } } var buildInGlyph = _imageService.GetImage(ImageType.Keyword); foreach (var s in Builtins.BuiltinList) { completions.Add(new EditorCompletionEntry(s, s, string.Empty, buildInGlyph)); } } return(Task.FromResult <IReadOnlyCollection <ICompletionEntry> >(completions)); }
private static FunctionCall GetFunctionCall(IRIntellisenseContext context) { // Safety checks var funcCall = context.AstRoot.GetNodeOfTypeFromPosition <FunctionCall>(context.Position); if (funcCall == null && context.Position > 0) { // This may be the case when brace is not closed and the position is at the very end. // Try stepping back one character and retry. If we find the function call, check that // indeed a) brace is not closed and b) position is at the very end of the function // signature in order to avoid false positive in case of func()|. funcCall = context.AstRoot.GetNodeOfTypeFromPosition <FunctionCall>(context.Position - 1); if (funcCall == null || funcCall.CloseBrace != null || context.Position != funcCall.End) { return(null); } return(funcCall); } if (funcCall == null || context.Position < funcCall.OpenBrace.End || context.Position >= funcCall.SignatureEnd) { return(null); } return(funcCall); }
/// <summary> /// Calculates span in the text buffer that contains data /// applicable to the current completion session. A tracking /// span will be created over it and editor will grow and shrink /// tracking span as user types and filter completion session /// based on the data inside the tracking span. /// </summary> private Span?GetApplicableSpan(IRIntellisenseContext context, ICompletionSession session) { var selectedSpans = session.TextView.Selection.SelectedSpans; if (selectedSpans.Count == 1 && selectedSpans[0].Span.Length > 0) { var spans = session.TextView.MapDownToR(selectedSpans[0]); if (spans.Count > 0) { return(spans[0].Span); } return(null); } var snapshot = _textBuffer.CurrentSnapshot; var line = snapshot.GetLineFromPosition(context.Position); var lineText = snapshot.GetText(line.Start, line.Length); var linePosition = context.Position - line.Start; // If completion is in comment, such as in Roxygen, // allow any text since it is no longer language-specific var document = context.EditorBuffer.GetEditorDocument <IREditorDocument>(); if (document.IsPositionInComment(context.Position)) { var typedText = lineText.TextBeforePosition(linePosition); return(new Span(context.Position - typedText.Length, typedText.Length)); } var start = 0; var end = line.Length; for (var i = linePosition - 1; i >= 0; i--) { var ch = lineText[i]; if (!RTokenizer.IsIdentifierCharacter(ch)) { start = i + 1; break; } } for (var i = linePosition; i < lineText.Length; i++) { var ch = lineText[i]; if (!RTokenizer.IsIdentifierCharacter(ch)) { end = i; break; } } if (start < end) { return(new Span(start + line.Start, end - start)); } return(new Span(context.Position, 0)); }
private async Task <IEnumerable <IPackageInfo> > GetPackagesAsync(IRIntellisenseContext context) { if (context.IsCaretInNamespace()) { return(GetSpecificPackage(context)); } return(await GetAllFilePackagesAsync(context)); }
/// <summary> /// Retrieves list of packages declared in the file via 'library' statements /// </summary> /// <param name="context"></param> /// <returns></returns> private Task <IEnumerable <IPackageInfo> > GetAllFilePackagesAsync(IRIntellisenseContext context) { var loadedPackages = _session?.LoadedPackageNames ?? Enumerable.Empty <string>(); var filePackageNames = context.AstRoot.GetFilePackageNames(); var allPackageNames = PackageIndex.PreloadedPackages.Union(filePackageNames).Union(loadedPackages); return(_packageIndex.GetPackagesInfoAsync(allPackageNames)); }
public static bool IsCaretInNamespace(this IRIntellisenseContext context, IEditorView view) { var bufferPosition = context.Session.View.GetCaretPosition(context.EditorBuffer); if (bufferPosition != null) { return(bufferPosition.Snapshot.IsPositionInNamespace(bufferPosition.Position)); } return(false); }
private IEnumerable <IPackageInfo> GetPackages(IRIntellisenseContext context) { if (context.IsCaretInNamespace()) { return(GetSpecificPackage(context)); } return(_taskService.Wait(() => GetAllFilePackagesAsync(context), out var result, _asyncWaitTimeout) ? result : Enumerable.Empty <IPackageInfo>()); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); if (_snippetInformationSource?.InformationSource != null && !context.IsCaretInNamespace()) { var snippets = _snippetInformationSource.InformationSource.Snippets; completions.AddRange(snippets.Select(info => new EditorCompletionEntry(info.Name, info.Name, info.Description, _snippetGlyph))); } return(completions); }
private int ComputeActiveParameter(IRIntellisenseContext context, ISignatureInfo signatureInfo) { var settings = _services.GetService <IREditorSettings>(); var parameterIndex = signatureInfo.ComputeCurrentParameter(context.EditorBuffer.CurrentSnapshot, context.AstRoot, context.Position, settings); if (parameterIndex < signatureInfo.Arguments.Count) { return(parameterIndex); } return(signatureInfo.Arguments.Count > 0 ? signatureInfo.Arguments.Count - 1 : 0); }
private IEnumerable <IPackageInfo> GetPackages(IRIntellisenseContext context) { if (context.IsCaretInNameSpace()) { return(GetSpecificPackage(context)); } var t = GetAllFilePackagesAsync(context); t.Wait(_asyncWaitTimeout); return(t.IsCompleted ? t.Result : Enumerable.Empty <IPackageInfo>()); }
public IEnumerable <IRFunctionSignatureHelp> GetSignaturesAsync(IRIntellisenseContext context, Action <IEnumerable <IRFunctionSignatureHelp> > callback) { var snapshot = context.EditorBuffer.CurrentSnapshot; // Retrieve parameter positions from the current text buffer snapshot var signatureInfo = context.AstRoot.GetSignatureInfoFromBuffer(snapshot, context.Position); if (signatureInfo == null) { return(null); } return(GetSignaturesAsync(signatureInfo, context, callback)); }
public Task <Hover> GetHoverAsync(IRIntellisenseContext context, CancellationToken ct) { var tcs = new TaskCompletionSource <Hover>(); using (context.AstReadLock()) { var infos = _signatureEngine.GetQuickInfosAsync(context, e => { var r = !ct.IsCancellationRequested ? ToHover(e.ToList(), context.EditorBuffer) : null; tcs.TrySetResult(r); }); return(infos != null?Task.FromResult(ToHover(infos.ToList(), context.EditorBuffer)) : tcs.Task); } }
private IEnumerable <IPackageInfo> GetPackages(IRIntellisenseContext context) { if (context.IsCaretInNamespace()) { return(GetSpecificPackage(context)); } var t = GetAllFilePackagesAsync(context); return(_taskService.Wait(t, CancellationToken.None, _asyncWaitTimeout) ? t.Result : Enumerable.Empty <IPackageInfo>()); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context) { var completions = new List <ICompletionEntry>(); if (_snippetInformationSource?.InformationSource != null && !context.IsCaretInNamespace()) { foreach (ISnippetInfo info in _snippetInformationSource.InformationSource.Snippets) { completions.Add(new EditorCompletionEntry(info.Name, info.Name, info.Description, _snippetGlyph)); } } return(completions); }
public CompletionList GetCompletions(IRIntellisenseContext context) { context.EditorBuffer.GetEditorDocument <IREditorDocument>().EditorTree.EnsureTreeReady(); var providers = _completionEngine.GetCompletionForLocation(context); if (providers == null || providers.Count == 0) { return(new CompletionList()); } // Do not generate thousands of items, VSCode cannot handle that. // Filter based on the text typed so far right away. var prefix = GetFilterPrefix(context); var completions = new List <ICompletionEntry>(); var sort = true; foreach (var provider in providers) { var entries = provider.GetEntries(context, prefix); if (entries.Count > 0) { completions.AddRange(entries); } sort &= provider.AllowSorting; } if (sort) { completions.Sort(new CompletionEntryComparer(StringComparison.OrdinalIgnoreCase)); completions.RemoveDuplicates(new CompletionEntryComparer(StringComparison.Ordinal)); } var sorted = new List <ICompletionEntry>(); sorted.AddRange(completions.Where(c => c.DisplayText.EndsWith("="))); sorted.AddRange(completions.Where(c => char.IsLetter(c.DisplayText[0]) && !c.DisplayText.EndsWith("="))); var items = sorted .Select(c => new CompletionItem { Label = c.DisplayText, InsertText = c.InsertionText, Kind = (CompletionItemKind)c.ImageSource, Documentation = c.Description, Data = c.Data is string?JToken.FromObject((string)c.Data) : null }).ToList(); return(new CompletionList(false, items)); }
/// <summary> /// Extracts information on the current function in the completion context, if any. /// </summary> /// <returns></returns> private IFunctionInfo GetFunctionInfo(IRIntellisenseContext context) { // Retrieve parameter positions from the current text buffer snapshot IFunctionInfo functionInfo = null; var parametersInfo = context.AstRoot.GetSignatureInfoFromBuffer(context.EditorBuffer.CurrentSnapshot, context.Position); if (parametersInfo != null) { // User-declared functions take priority functionInfo = context.AstRoot.GetUserFunctionInfo(parametersInfo.FunctionName, context.Position) ?? _functionIndex.GetFunctionInfo(parametersInfo.FunctionName, null); } return(functionInfo); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); var functionGlyph = _imageService.GetImage(ImageType.ValueType); // Get AST function call for the parameter completion var funcCall = GetFunctionCall(context); if (funcCall == null) { return(completions); } // Get collection of function signatures from documentation (parsed RD file) var functionInfo = GetFunctionInfo(context); if (functionInfo == null) { return(completions); } // Collect parameter names from all signatures IEnumerable <KeyValuePair <string, IArgumentInfo> > arguments = new Dictionary <string, IArgumentInfo>(); foreach (var signature in functionInfo.Signatures) { var args = new Dictionary <string, IArgumentInfo>(); foreach (var arg in signature.Arguments.Where(x => !string.IsNullOrEmpty(x.Name))) { args[arg.Name] = arg; } arguments = arguments.Union(args); } // Add names of arguments that are not yet specified to the completion // list with '=' sign so user can tell them from function names. var declaredArguments = funcCall.Arguments.Where(x => x is NamedArgument).Select(x => ((NamedArgument)x).Name); var possibleArguments = arguments.Where(x => !x.Key.EqualsOrdinal("...") && !declaredArguments.Contains(x.Key, StringComparer.OrdinalIgnoreCase)); foreach (var arg in possibleArguments) { var displayText = arg.Key + " ="; var insertionText = arg.Key + " = "; completions.Add(new EditorCompletionEntry(displayText, insertionText, arg.Value.Description, functionGlyph)); } return(completions); }
/// <summary> /// Retrieves name of the package in 'package::' statement /// so intellisense can show list of functions available /// in the specific package. /// </summary> private IEnumerable <IPackageInfo> GetSpecificPackage(IRIntellisenseContext context) { var packages = new List <IPackageInfo>(); var snapshot = context.EditorBuffer.CurrentSnapshot; var colons = 0; for (var i = context.Position - 1; i >= 0; i--, colons++) { var ch = snapshot[i]; if (ch != ':') { break; } } if (colons > 1 && colons < 4) { var packageName = string.Empty; var start = 0; var end = context.Position - colons; for (var i = end - 1; i >= 0; i--) { var ch = snapshot[i]; if (!RTokenizer.IsIdentifierCharacter(ch)) { start = i + 1; break; } } if (start < end) { packageName = snapshot.GetText(TextRange.FromBounds(start, end)); if (packageName.Length > 0) { context.InternalFunctions = colons == 3; var package = GetPackageByName(packageName); if (package != null) { packages.Add(package); } } } } return(packages); }
private static bool ShouldProvideCompletions(IRIntellisenseContext context, out FunctionCall funcCall) { // Safety checks funcCall = context.AstRoot.GetNodeOfTypeFromPosition <FunctionCall>(context.Position); if (funcCall?.OpenBrace == null || funcCall.Arguments == null) { return(false); } if (context.Position < funcCall.OpenBrace.End || context.Position >= funcCall.SignatureEnd) { return(false); } return(true); }
public Task <IReadOnlyCollection <ICompletionEntry> > GetEntriesAsync(IRIntellisenseContext context, string prefixFilter = null) { var snapshot = context.EditorBuffer.CurrentSnapshot; var lineStart = snapshot.GetLineFromPosition(context.Position).Start; var searchText = snapshot.GetText(new TextRange(lineStart, context.Position - lineStart)).Trim(); var entries = new List <ICompletionEntry>(); foreach (var text in _history.Search(searchText)) { var displayText = GetDisplayText(text); var descriptionText = GetDescriptionText(text, displayText); entries.Add(new EditorCompletionEntry(displayText, text, descriptionText, _glyph)); } return(Task.FromResult <IReadOnlyCollection <ICompletionEntry> >(entries)); }
private static string GetFilterPrefix(IRIntellisenseContext context) { var snapshot = context.EditorBuffer.CurrentSnapshot; var line = snapshot.GetLineFromPosition(context.Position); var text = line.GetText(); int i; var offset = context.Position - line.Start; for (i = offset - 1; i >= 0 && RTokenizer.IsIdentifierCharacter(text[i]); i--) { } i = Math.Min(offset, i + 1); return(text.Substring(i, offset - i)); }
public async Task <IReadOnlyCollection <ICompletionEntry> > GetEntriesAsync(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); var infoSource = _snippetInformationSource?.InformationSource; var packages = (await GetPackagesAsync(context)).ToList(); var packageName = packages.Count == 1 ? packages[0].Name : null; var caretInNamespace = !context.IsCaretInNamespace(out var showInternalFunctions); // Get list of functions in the package foreach (var pkg in packages) { Debug.Assert(pkg != null); var functions = pkg.Functions; if (functions == null) { continue; } if (!string.IsNullOrEmpty(prefixFilter)) { functions = functions.Where(f => f.Name.StartsWith(prefixFilter)); } foreach (var function in functions.Where(f => !f.IsInternal || f.IsInternal == showInternalFunctions)) { // Snippets are suppressed if user typed namespace if (!caretInNamespace && infoSource != null) { if (infoSource.IsSnippet(function.Name)) { continue; } } var glyph = function.ItemType == NamedItemType.Constant ? function.IsInternal ? _internalConstantGlyph : _constantGlyph : function.IsInternal ? _internalFunctionGlyph : _functionGlyph; if (function.Name.IndexOf('`') >= 0) { } var completion = new RFunctionCompletionEntry(function.Name.RemoveBackticks(), function.Name.BacktickName(), function.Description, glyph, packageName, _functionIndex, context.Session); completions.Add(completion); } } return(completions); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context) { var completions = new List <ICompletionEntry>(); var line = context.EditorBuffer.CurrentSnapshot.GetLineFromPosition(context.Position); var rawLineText = line.GetText(); var lineText = rawLineText.TrimStart(); // Check that we are inside the Roxygen comment if (!lineText.StartsWith("#'") || context.Position < rawLineText.Length - lineText.Length + 2) { return(completions); } completions.AddRange(RoxygenKeywords.Keywords.Select(k => new EditorCompletionEntry(k, k, string.Empty, _glyph))); return(completions); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context) { var completions = new List <ICompletionEntry>(); var line = context.EditorBuffer.CurrentSnapshot.GetLineFromPosition(context.Position); var rawLineText = line.GetText(); var lineText = rawLineText.TrimStart(); var positionInLine = context.Position - line.Start; var typedText = lineText.TextBeforePosition(positionInLine); // Check that we are inside the Roxygen comment AND just typed character is @ if (lineText.StartsWith("#'") && positionInLine >= 2 && typedText.StartsWithOrdinal("@")) { completions.AddRange(RoxygenKeywords.Keywords.Select(k => new EditorCompletionEntry(k, k, string.Empty, _glyph))); } return(completions); }
public IReadOnlyCollection <ICompletionEntry> GetEntries(IRIntellisenseContext context, string prefixFilter = null) { var completions = new List <ICompletionEntry>(); var directory = _enteredDirectory; try { // If we are running async directory fetching, wait a bit _task?.Wait(500); } catch (OperationCanceledException) { } try { // If directory is set, then the async task did complete if (!string.IsNullOrEmpty(_rootDirectory)) { if (_mode == Mode.WorkingDirectory) { directory = Path.Combine(_rootDirectory, _enteredDirectory); } else if (_mode == Mode.UserDirectory) { var subDirectory = _enteredDirectory.Length > 1 ? _enteredDirectory.Substring(2) : _enteredDirectory; directory = Path.Combine(_rootDirectory, subDirectory); } } } catch (ArgumentException) { } try { if (!string.IsNullOrEmpty(directory)) { IEnumerable <ICompletionEntry> entries; if (_forceR || _workflow.RSession.IsRemote) { var t = GetRemoteDirectoryItemsAsync(directory); entries = t.WaitTimeout(_forceR ? 5000 : 1000); } else { entries = GetLocalDirectoryItems(directory); } completions.AddRange(entries); } } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (ArgumentException) { } catch (TimeoutException) { } return(completions); }
public async Task <CompletionList> GetCompletionsAsync(IRIntellisenseContext context) { context.EditorBuffer.GetEditorDocument <IREditorDocument>().EditorTree.EnsureTreeReady(); var providers = _completionEngine.GetCompletionForLocation(context); if (providers == null || providers.Count == 0) { return(new CompletionList()); } // Do not generate thousands of items, VSCode cannot handle that. // Filter based on the text typed so far right away. var prefix = GetFilterPrefix(context); var completions = (await Task.WhenAll(providers.Select(p => p.GetEntriesAsync(context, prefix)))).SelectMany(t => t).ToList(); if (providers.All(p => p.AllowSorting)) { completions.Sort(new CompletionEntryComparer(StringComparison.OrdinalIgnoreCase)); completions.RemoveDuplicates(new CompletionEntryComparer(StringComparison.Ordinal)); } var sorted = new List <ICompletionEntry>(); sorted.AddRange(completions.Where(c => c.DisplayText.EndsWith("=", StringComparison.Ordinal))); sorted.AddRange(completions.Where(c => char.IsLetter(c.DisplayText[0]) && !c.DisplayText.EndsWith("=", StringComparison.Ordinal))); var items = sorted .Select(c => new CompletionItem { label = c.DisplayText, insertText = c.InsertionText, kind = (CompletionItemKind)c.ImageSource, documentation = new MarkupContent { kind = "plaintext", value = c.Description }, data = c.Data is string?JToken.FromObject((string)c.Data) : null }).ToList(); return(new CompletionList { isIncomplete = true, items = items.ToArray() }); }