/// <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());
        }
Example #2
0
        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