/// <summary> /// Generates completion options for a manager script. /// </summary> /// <param name="code">Source code.</param> /// <param name="offset">Offset of the cursor/caret in the source code.</param> /// <param name="controlSpace">True iff this intellisense request was generated by the user pressing control + space.</param> /// <returns>True if any completion options are found. False otherwise.</returns> public bool GenerateScriptCompletions(string code, int offset, bool controlSpace = false) { CSharpParser parser = new CSharpParser(); SyntaxTree syntaxTree = parser.Parse(code); string fileName = Path.GetTempFileName(); if (!File.Exists(fileName)) { File.Create(fileName).Close(); } File.WriteAllText(fileName, code); syntaxTree.FileName = fileName; syntaxTree.Freeze(); // Should probably take into account which namespaces the user is using and load the needed assemblies into the CSharpCompletion object // string usings = syntaxTree.Descendants.OfType<UsingDeclaration>().Select(x => x.ToString()).Aggregate((x, y) => x + /* Environment.NewLine + */ y); IDocument document = new ReadOnlyDocument(new StringTextSource(code), syntaxTree.FileName); completionResult = completion.GetCompletions(document, offset, controlSpace); // Set the trigger word for later use. triggerWord = controlSpace ? completionResult.TriggerWord : string.Empty; // If the user pressed control space, we assume they are trying to generate completions for a partially typed word. // In this situation we need to filter the results based on what they have already typed. // The exception is if the most recent character is a period. // No idea why NRefactory can't do this for us. if (controlSpace && !string.IsNullOrEmpty(completionResult.TriggerWord) && code[offset - 1] != '.') { // Filter items. completionResult.CompletionData = completionResult.CompletionData.Where(item => GetMatchQuality(item.CompletionText, completionResult.TriggerWord) > 0).ToList(); } List <CompletionData> completionList = completionResult.CompletionData.Select(x => x as CompletionData).Where(x => x != null).OrderBy(x => x.CompletionText).ToList(); view.Populate(completionList); if (controlSpace && !string.IsNullOrEmpty(completionResult.TriggerWord)) { view.SelectItem(completionList.IndexOf(completionList.OrderByDescending(x => GetMatchQuality(x.CompletionText, completionResult.TriggerWord)).FirstOrDefault())); } return(completionList.Any()); }
private void ShowCompletion(string enteredText, bool controlSpace) { if (!controlSpace) { Debug.WriteLine("Code Completion: TextEntered: " + enteredText); } else { Debug.WriteLine("Code Completion: Ctrl+Space"); } //only process csharp files if (String.IsNullOrEmpty(textEditor.Document.FileName)) { return; } var fileExtension = Path.GetExtension(textEditor.Document.FileName); fileExtension = fileExtension != null?fileExtension.ToLower() : null; //check file extension to be a c# file (.cs, .csx, etc.) if (fileExtension == null || (!fileExtension.StartsWith(".cs"))) { return; } if (completionWindow == null) { CodeCompletionResult results = null; try { results = CSharpCompletion.GetCompletions(textEditor.Document, textEditor.CaretOffset, controlSpace); } catch (Exception exception) { Debug.WriteLine("Error in getting completion: " + exception); } if (results == null) { return; } if (insightWindow == null && results.OverloadProvider != null) { insightWindow = new OverloadInsightWindow(textEditor.TextArea); insightWindow.Provider = results.OverloadProvider; insightWindow.Show(); insightWindow.Closed += (o, args) => insightWindow = null; return; } if (completionWindow == null && results != null && results.CompletionData.Any()) { // Open code completion after the user has pressed dot: completionWindow = new CompletionWindow(textEditor.TextArea); completionWindow.CloseWhenCaretAtBeginning = controlSpace; completionWindow.StartOffset -= results.TriggerWordLength; //completionWindow.EndOffset -= results.TriggerWordLength; IList <ICompletionData> data = completionWindow.CompletionList.CompletionData; foreach (var completion in results.CompletionData.OrderBy(item => item.Text)) { data.Add(completion); } if (results.TriggerWordLength > 0) { //completionWindow.CompletionList.IsFiltering = false; completionWindow.CompletionList.SelectItem(results.TriggerWord); } completionWindow.Show(); completionWindow.Closed += (o, args) => completionWindow = null; } }//end if //update the insight window if (!string.IsNullOrEmpty(enteredText) && insightWindow != null) { //whenver text is entered update the provider var provider = insightWindow.Provider as CSharpOverloadProvider; if (provider != null) { //since the text has not been added yet we need to tread it as if the char has already been inserted provider.Update(textEditor.Document, textEditor.CaretOffset); //if the windows is requested to be closed we do it here if (provider.RequestClose) { insightWindow.Close(); insightWindow = null; } } } }//end method