Пример #1
0
        public IEnumerable <CompletionData> CreateProvider(AutoCompleteRequest request)
        {
            request.Column = request.Column - request.WordToComplete.Length;
            var completionContext = new BufferContext(request, _parser);

            var partialWord = request.WordToComplete;

            var project = _solution.ProjectContainingFile(request.FileName);

            var contextProvider = new DefaultCompletionContextProvider(completionContext.Document, completionContext.ParsedContent.UnresolvedFile);

            if (project.CompilerSettings != null)
            {
                var conditionalSymbols = project.CompilerSettings.ConditionalSymbols;
                foreach (var symbol in conditionalSymbols)
                {
                    contextProvider.AddSymbol(symbol);
                }
            }

            var instantiating = IsInstantiating(completionContext.NodeCurrentlyUnderCursor);

            var engine = new CSharpCompletionEngine(completionContext.Document
                                                    , contextProvider
                                                    , new CompletionDataFactory(project
                                                                                , partialWord
                                                                                , instantiating
                                                                                , request
                                                                                , _config)
                                                    , completionContext.ParsedContent.ProjectContent
                                                    , completionContext.ResolveContext)
            {
                EolMarker = Environment.NewLine
            };

            engine.AutomaticallyAddImports = request.WantImportableTypes;
            _logger.Debug("Getting Completion Data");

            IEnumerable <CompletionData> data = engine.GetCompletionData(completionContext.CursorPosition, true).Cast <CompletionData>();

            _logger.Debug("Got Completion Data");
            return(data.Where(d => d != null && d.CompletionText.IsValidCompletionFor(partialWord))
                   .FlattenOverloads()
                   .RemoveDupes()
                   .OrderByDescending(d => d.RequiredNamespaceImport != null ? 0 : 1)
                   .ThenByDescending(d => d.CompletionText.IsValidCompletionStartsWithExactCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsValidCompletionStartsWithIgnoreCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsCamelCaseMatch(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsSubsequenceMatch(partialWord))
                   .ThenBy(d => d.CompletionText));
        }
Пример #2
0
        IEnumerable <Common.ICompletionData> GetCSharpCompletionData(ReadOnlyDocument doc, string editorText, int offset, string fileName, bool isControlSpace = true) // not the best way to put in the whole string every time
        {
            if (editorText[offset] != '.')                                                                                                                             //we may be at the partially complete word
            {
                for (int i = offset - 1; i >= 0; i--)
                {
                    if (SimpleCodeCompletion.Delimiters.Contains(editorText[i]))
                    {
                        offset = i + 1;
                        break;
                    }
                }
            }

            //test for C# completion
            var location = doc.GetLocation(offset);

            var syntaxTree = new CSharpParser().Parse(editorText, fileName);

            syntaxTree.Freeze();
            var unresolvedFile = syntaxTree.ToTypeSystem();

            Project = Project.AddOrUpdateFiles(unresolvedFile);

            //note project should be reassigned/recreated every time we add asms or file

            //IProjectContent project = new CSharpProjectContent();
            //project = project.AddAssemblyReferences(builtInLibs.Value);
            //project = project.AddOrUpdateFiles(unresolvedFile);

            //IProjectContent project = new CSharpProjectContent().AddAssemblyReferences(builtInLibs.Value).AddOrUpdateFiles(unresolvedFile);

            var completionContextProvider = new DefaultCompletionContextProvider(doc, unresolvedFile);

            var compilation = Project.CreateCompilation();
            var resolver    = unresolvedFile.GetResolver(compilation, location);

            var engine = new CSharpCompletionEngine(doc,
                                                    completionContextProvider,
                                                    new SimpleCompletionDataFactory(resolver),
                                                    Project,
                                                    resolver.CurrentTypeResolveContext);

            var data = engine.GetCompletionData(offset, isControlSpace);

            return(data.PrepareForDisplay().ToCommon());
        }
Пример #3
0
        public IEnumerable <ICompletionData> CreateProvider(AutoCompleteRequest request)
        {
            request.Column = request.Column - request.WordToComplete.Length;

            var completionContext = new BufferContext(request, _parser);

            var partialWord = request.WordToComplete;

            var project = _solution.ProjectContainingFile(request.FileName);

            ICompletionContextProvider contextProvider = new DefaultCompletionContextProvider
                                                             (completionContext.Document, completionContext.ParsedContent.UnresolvedFile);

            var instantiating = IsInstantiating(completionContext.NodeCurrentlyUnderCursor);

            var engine = new CSharpCompletionEngine
                             (completionContext.Document
                             , contextProvider
                             , new CompletionDataFactory
                                 (project
                                 , partialWord
                                 , instantiating
                                 , request.WantDocumentationForEveryCompletionResult)
                             , completionContext.ParsedContent.ProjectContent
                             , completionContext.ResolveContext)
            {
                EolMarker = Environment.NewLine
            };

            _logger.Debug("Getting Completion Data");

            IEnumerable <ICompletionData> data = engine.GetCompletionData(completionContext.CursorPosition, true);

            _logger.Debug("Got Completion Data");
            return(data.Where(d => d != null && d.CompletionText.IsValidCompletionFor(partialWord))
                   .FlattenOverloads()
                   .RemoveDupes()
                   .OrderByDescending(d => d.CompletionText.IsValidCompletionStartsWithExactCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsValidCompletionStartsWithIgnoreCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsCamelCaseMatch(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsSubsequenceMatch(partialWord))
                   .ThenBy(d => d.CompletionText));
        }
Пример #4
0
        public IEnumerable <ICompletionData> CreateProvider(AutoCompleteRequest request)
        {
            var editorText  = request.Buffer ?? string.Empty;
            var filename    = request.FileName;
            var partialWord = request.WordToComplete ?? string.Empty;

            var doc            = new ReadOnlyDocument(editorText);
            var loc            = new TextLocation(request.Line, request.Column - partialWord.Length);
            int cursorPosition = doc.GetOffset(loc);

            //Ensure cursorPosition only equals 0 when editorText is empty, so line 1,column 1
            //completion will work correctly.
            cursorPosition = Math.Max(cursorPosition, 1);
            cursorPosition = Math.Min(cursorPosition, editorText.Length);


            var res  = _parser.ParsedContent(editorText, filename);
            var rctx = res.UnresolvedFile.GetTypeResolveContext(res.Compilation, loc);

            ICompletionContextProvider contextProvider = new DefaultCompletionContextProvider(doc, res.UnresolvedFile);
            var engine = new CSharpCompletionEngine(doc, contextProvider, new CompletionDataFactory(partialWord), res.ProjectContent, rctx)
            {
                EolMarker = Environment.NewLine
            };

            _logger.Debug("Getting Completion Data");

            IEnumerable <ICompletionData> data = engine.GetCompletionData(cursorPosition, true);

            _logger.Debug("Got Completion Data");
            return(data.Where(d => d != null && d.CompletionText.IsValidCompletionFor(partialWord))
                   .FlattenOverloads()
                   .RemoveDupes()
                   .OrderByDescending(d => d.CompletionText.IsValidCompletionStartsWithExactCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsValidCompletionStartsWithIgnoreCase(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsCamelCaseMatch(partialWord))
                   .ThenByDescending(d => d.CompletionText.IsSubsequenceMatch(partialWord))
                   .ThenBy(d => d.CompletionText));
        }
Пример #5
0
        ICompletionDataList InternalHandleCodeCompletion(CodeCompletionContext completionContext, char completionChar, bool ctrlSpace, ref int triggerWordLength)
        {
/*
 *                      if (textEditorData.CurrentMode is CompletionTextLinkMode) {
 *                              if (!((CompletionTextLinkMode)textEditorData.CurrentMode).TriggerCodeCompletion)
 *                                      return null;
 *                      } else if (textEditorData.CurrentMode is Mono.TextEditor.TextLinkEditMode) {
 *                              return null;
 *                      }*/
            if (Unit == null || CSharpParsedFile == null)
            {
                return(null);
            }
            var list   = new CompletionDataList();
            var engine = new CSharpCompletionEngine(
                textEditorData.Document,
                this,
                Document.GetProjectContext(),
                CSharpParsedFile.GetTypeResolveContext(Document.Compilation, document.Editor.Caret.Location) as CSharpTypeResolveContext,
                Unit,
                CSharpParsedFile
                );

            engine.MemberProvider   = typeSystemSegmentTree;
            engine.FormattingPolicy = FormattingPolicy.CreateOptions();
            engine.EolMarker        = textEditorData.EolMarker;
            engine.IndentString     = textEditorData.Options.IndentationString;
            list.AddRange(engine.GetCompletionData(completionContext.TriggerOffset, ctrlSpace));
            list.AutoCompleteEmptyMatch  = engine.AutoCompleteEmptyMatch;
            list.AutoSelect              = engine.AutoSelect;
            list.DefaultCompletionString = engine.DefaultCompletionString;
            list.CloseOnSquareBrackets   = engine.CloseOnSquareBrackets;
            if (ctrlSpace)
            {
                list.AutoCompleteUniqueMatch = true;
            }
            return(list.Count > 0 ? list : null);
        }
        public static IEnumerable <ICompletionData> DoCodeComplete(string editorText, int offset) // not the best way to put in the whole string every time
        {
            var doc      = new ReadOnlyDocument(editorText);
            var location = doc.GetLocation(offset);

            string parsedText = editorText; // TODO: Why are there different values in test cases?


            var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs");

            syntaxTree.Freeze();
            var unresolvedFile = syntaxTree.ToTypeSystem();

            var mb = new DefaultCompletionContextProvider(doc, unresolvedFile);

            IProjectContent pctx = new CSharpProjectContent();
            var             refs = new List <IUnresolvedAssembly> {
                mscorlib.Value, systemCore.Value, systemAssembly.Value
            };

            pctx = pctx.AddAssemblyReferences(refs);
            pctx = pctx.AddOrUpdateFiles(unresolvedFile);

            var cmp = pctx.CreateCompilation();

            var resolver3 = unresolvedFile.GetResolver(cmp, location);
            var engine    = new CSharpCompletionEngine(doc, mb, new TestCompletionDataFactory(resolver3), pctx, resolver3.CurrentTypeResolveContext);


            engine.EolMarker        = Environment.NewLine;
            engine.FormattingPolicy = FormattingOptionsFactory.CreateMono();

            var data = engine.GetCompletionData(offset, controlSpace: false);

            return(data);
        }
Пример #7
0
        public CodeCompletionResult GetCompletions(IDocument document, int offset, bool controlSpace, string usings, string variables = null)
        {
            var result = new CodeCompletionResult();

            if (String.IsNullOrEmpty(document.FileName))
            {
                return(result);
            }

            var completionContext = new CSharpCompletionContext(document, offset, projectContent, usings, variables);

            var completionFactory = new CSharpCompletionDataFactory(completionContext.TypeResolveContextAtCaret, completionContext);
            var cce = new CSharpCompletionEngine(
                completionContext.Document,
                completionContext.CompletionContextProvider,
                completionFactory,
                completionContext.ProjectContent,
                completionContext.TypeResolveContextAtCaret
                );

            cce.EolMarker        = Environment.NewLine;
            cce.FormattingPolicy = FormattingOptionsFactory.CreateSharpDevelop();


            var completionChar = completionContext.Document.GetCharAt(completionContext.Offset - 1);
            int startPos, triggerWordLength;
            IEnumerable <ICSharpCode.NRefactory.Completion.ICompletionData> completionData;

            if (controlSpace)
            {
                if (!cce.TryGetCompletionWord(completionContext.Offset, out startPos, out triggerWordLength))
                {
                    startPos          = completionContext.Offset;
                    triggerWordLength = 0;
                }
                completionData = cce.GetCompletionData(startPos, true);
                //this outputs tons of available entities
                //if (triggerWordLength == 0)
                //    completionData = completionData.Concat(cce.GetImportCompletionData(startPos));
            }
            else
            {
                startPos = completionContext.Offset;

                if (char.IsLetterOrDigit(completionChar) || completionChar == '_')
                {
                    if (startPos > 1 && char.IsLetterOrDigit(completionContext.Document.GetCharAt(startPos - 2)))
                    {
                        return(result);
                    }
                    completionData = cce.GetCompletionData(startPos, false);
                    startPos--;
                    triggerWordLength = 1;
                }
                else
                {
                    completionData    = cce.GetCompletionData(startPos, false);
                    triggerWordLength = 0;
                }
            }

            result.TriggerWordLength = triggerWordLength;
            result.TriggerWord       = completionContext.Document.GetText(completionContext.Offset - triggerWordLength, triggerWordLength);
            Debug.Print("Trigger word: '{0}'", result.TriggerWord);

            //cast to AvalonEdit completion data and add to results
            foreach (var completion in completionData)
            {
                var cshellCompletionData = completion as ICSharpCode.CodeCompletion.DataItems.CompletionData;
                if (cshellCompletionData != null)
                {
                    cshellCompletionData.TriggerWord       = result.TriggerWord;
                    cshellCompletionData.TriggerWordLength = result.TriggerWordLength;

                    if (completion is ICSharpCode.CodeCompletion.DataItems.EntityCompletionData)
                    {
                        string typename = String.Empty;

                        var entity = cshellCompletionData as ICSharpCode.CodeCompletion.DataItems.EntityCompletionData;

                        if (entity.Entity is ICSharpCode.NRefactory.TypeSystem.Implementation.DefaultResolvedTypeDefinition)
                        {
                            var def = entity.Entity as ICSharpCode.NRefactory.TypeSystem.Implementation.DefaultResolvedTypeDefinition;

                            typename = def.FullTypeName.ReflectionName;
                        }
                        else
                        {
                            typename = entity.Entity.DeclaringType.FullName;
                        }

                        Type type = Type.GetType(typename);

                        if (!AllowedType(type))
                        {
                            continue;
                        }
                    }

                    result.CompletionData.Add(cshellCompletionData);

                    // piggyback 'region' preprocessor to add our own
                    if (cshellCompletionData.DisplayText == "region")
                    {
                        DataItems.CompletionData import = new DataItems.CompletionData("import");
                        import.CompletionCategory = cshellCompletionData.CompletionCategory;
                        import.Image = cshellCompletionData.Image;
                        result.CompletionData.Add(import);
                    }
                }
            }

            //method completions
            if (!controlSpace)
            {
                // Method Insight
                var pce = new CSharpParameterCompletionEngine(
                    completionContext.Document,
                    completionContext.CompletionContextProvider,
                    completionFactory,
                    completionContext.ProjectContent,
                    completionContext.TypeResolveContextAtCaret
                    );

                var parameterDataProvider = pce.GetParameterDataProvider(completionContext.Offset, completionChar);
                result.OverloadProvider = parameterDataProvider as IOverloadProvider;
            }

            return(result);
        }
Пример #8
0
        public CodeCompletionResult GetCompletions(IDocument document, int offset, bool controlSpace, string usings)
        {
            var result = new CodeCompletionResult();

            if (String.IsNullOrEmpty(document.FileName))
            {
                return(result);
            }

            var completionContext = new CSharpCompletionContext(document, offset, projectContent, usings);

            var completionFactory = new CSharpCompletionDataFactory(completionContext.TypeResolveContextAtCaret, completionContext);
            var cce = new CSharpCompletionEngine(
                completionContext.Document,
                completionContext.CompletionContextProvider,
                completionFactory,
                completionContext.ProjectContent,
                completionContext.TypeResolveContextAtCaret
                );

            cce.EolMarker        = Environment.NewLine;
            cce.FormattingPolicy = FormattingOptionsFactory.CreateSharpDevelop();


            var completionChar = completionContext.Document.GetCharAt(completionContext.Offset - 1);
            int startPos, triggerWordLength;
            IEnumerable <ICSharpCode.NRefactory.Completion.ICompletionData> completionData;

            if (controlSpace)
            {
                if (!cce.TryGetCompletionWord(completionContext.Offset, out startPos, out triggerWordLength))
                {
                    startPos          = completionContext.Offset;
                    triggerWordLength = 0;
                }
                completionData = cce.GetCompletionData(startPos, true);
                //this outputs tons of available entities
                //if (triggerWordLength == 0)
                //    completionData = completionData.Concat(cce.GetImportCompletionData(startPos));
            }
            else
            {
                startPos = completionContext.Offset;

                if (char.IsLetterOrDigit(completionChar) || completionChar == '_')
                {
                    if (startPos > 1 && char.IsLetterOrDigit(completionContext.Document.GetCharAt(startPos - 2)))
                    {
                        return(result);
                    }
                    completionData = cce.GetCompletionData(startPos, false);
                    startPos--;
                    triggerWordLength = 1;
                }
                else
                {
                    completionData    = cce.GetCompletionData(startPos, false);
                    triggerWordLength = 0;
                }
            }

            result.TriggerWordLength = triggerWordLength;
            result.TriggerWord       = completionContext.Document.GetText(completionContext.Offset - triggerWordLength, triggerWordLength);
            Debug.Print("Trigger word: '{0}'", result.TriggerWord);

            //cast to AvalonEdit completion data and add to results
            foreach (var completion in completionData)
            {
                var cshellCompletionData = completion as CompletionData;
                if (cshellCompletionData != null)
                {
                    cshellCompletionData.TriggerWord       = result.TriggerWord;
                    cshellCompletionData.TriggerWordLength = result.TriggerWordLength;
                    result.CompletionData.Add(cshellCompletionData);
                }
            }

            //method completions
            if (!controlSpace)
            {
                // Method Insight
                var pce = new CSharpParameterCompletionEngine(
                    completionContext.Document,
                    completionContext.CompletionContextProvider,
                    completionFactory,
                    completionContext.ProjectContent,
                    completionContext.TypeResolveContextAtCaret
                    );

                var parameterDataProvider = pce.GetParameterDataProvider(completionContext.Offset, completionChar);
                result.OverloadProvider = parameterDataProvider as IOverloadProvider;
            }

            return(result);
        }
        bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace)
        {
            CSharpCompletionContext completionContext;

            if (fileContent == null)
            {
                completionContext = CSharpCompletionContext.Get(editor);
            }
            else
            {
                completionContext = CSharpCompletionContext.Get(editor, context, currentLocation, fileContent);
            }
            if (completionContext == null)
            {
                return(false);
            }

            int caretOffset;

            if (fileContent == null)
            {
                caretOffset     = editor.Caret.Offset;
                currentLocation = editor.Caret.Location;
            }
            else
            {
                caretOffset = completionContext.Document.GetOffset(currentLocation);
            }

            var completionFactory = new CSharpCompletionDataFactory(completionContext, new CSharpResolver(completionContext.TypeResolveContextAtCaret));

            CSharpCompletionEngine cce = new CSharpCompletionEngine(
                completionContext.Document,
                completionContext.CompletionContextProvider,
                completionFactory,
                completionContext.ProjectContent,
                completionContext.TypeResolveContextAtCaret
                );
            var formattingOptions = CSharpFormattingPolicies.Instance.GetProjectOptions(completionContext.Compilation.GetProject());

            cce.FormattingPolicy = formattingOptions.OptionsContainer.GetEffectiveOptions();
            cce.EolMarker        = DocumentUtilities.GetLineTerminator(completionContext.Document, currentLocation.Line);

            cce.IndentString = editor.Options.IndentationString;
            int startPos, triggerWordLength;
            IEnumerable <ICompletionData> completionData;

            if (ctrlSpace)
            {
                if (!cce.TryGetCompletionWord(caretOffset, out startPos, out triggerWordLength))
                {
                    startPos          = caretOffset;
                    triggerWordLength = 0;
                }
                completionData = cce.GetCompletionData(startPos, true);
                completionData = completionData.Concat(cce.GetImportCompletionData(startPos));
            }
            else
            {
                startPos = caretOffset;
                if (char.IsLetterOrDigit(completionChar) || completionChar == '_')
                {
                    if (startPos > 1 && char.IsLetterOrDigit(completionContext.Document.GetCharAt(startPos - 2)))
                    {
                        return(false);
                    }
                    completionData = cce.GetCompletionData(startPos, false);
                    startPos--;
                    triggerWordLength = 1;
                }
                else
                {
                    completionData    = cce.GetCompletionData(startPos, false);
                    triggerWordLength = 0;
                }
            }

            DefaultCompletionItemList list = new DefaultCompletionItemList();

            list.Items.AddRange(FilterAndAddTemplates(editor, completionData.Cast <ICompletionItem>().ToList()));
            if (list.Items.Count > 0 && (ctrlSpace || cce.AutoCompleteEmptyMatch))
            {
                list.SortItems();
                list.PreselectionLength  = caretOffset - startPos;
                list.PostselectionLength = Math.Max(0, startPos + triggerWordLength - caretOffset);
                list.SuggestedItem       = list.Items.FirstOrDefault(i => i.Text == cce.DefaultCompletionString);
                editor.ShowCompletionWindow(list);
                return(true);
            }

            if (!ctrlSpace)
            {
                // Method Insight
                var pce = new CSharpParameterCompletionEngine(
                    completionContext.Document,
                    completionContext.CompletionContextProvider,
                    completionFactory,
                    completionContext.ProjectContent,
                    completionContext.TypeResolveContextAtCaret
                    );
                var newInsight = pce.GetParameterDataProvider(caretOffset, completionChar) as CSharpMethodInsight;
                if (newInsight != null && newInsight.items.Count > 0)
                {
                    newInsight.UpdateHighlightedParameter(pce);
                    newInsight.Show();
                    return(true);
                }
            }
            return(false);
        }
        //// todo: eliminate this method later
        //private static void AugmentProjectModelWithAlgorithmBase(ProjectModel model)
        //{
        //    model.Children.Add(QcAlgorithmFileModel.Value);
        //}

        public static ProjectAnalysisResult RunFullProjectAnalysis(ProjectAnalysisRequest projectAnalysisRequest)
        {
            Stopwatch sw = Stopwatch.StartNew();

            ProjectAnalysisResult projectAnalysisResult = new ProjectAnalysisResult();
            ProjectModel          projectModel          = projectAnalysisRequest.ProjectModel;

            // todo: Ask Jared why QCAlgorithm is a partial class and why it's not included in "common"

#if false
            // ************************************************************************************
            // NOTE:  In order to get this project building cleanly, with minimal dependencies
            // before checking into Github, I've removed all hard QuantConnect dependencies,
            // including the QCAlgorithm.cs embedded resource and the assembly references to
            // QuantConnect.Algorithm.Interface

            // Augment the project model with the QCAgorithm base class
            // projectModel.Children.Add(QcAlgorithmFileModel.Value);

            // ************************************************************************************
#endif

            // Set up the project (if not already done)
            if (projectModel.ProjectContent == null)
            {
                projectModel.ProjectContent = new CSharpProjectContent();
                projectModel.ProjectContent = projectModel.ProjectContent.AddAssemblyReferences(QCReferences.Value);
            }

            // For each new file, we need to integrate it into the project content
            var fileModelsInProject = projectModel.GetFileDescendants().ToArray();
            foreach (var fileModelInProject in fileModelsInProject)
            {
                IntegrateFileModel(projectModel, fileModelInProject);
            }

            // We can return now if no code completion was requested
            if (projectAnalysisRequest.CodeCompletionParameters == null)
            {
                projectAnalysisResult.TimeElapsed = sw.Elapsed;
                return(projectAnalysisResult);
            }

            // Now it's time to give attention specifically to the matter of resolving the code completion
            // options.  This, of course, requires a deeper analysis of the specified file...

            var codeCompletionParams = projectAnalysisRequest.CodeCompletionParameters;

            // Locate the file in the project
            ProjectFileModel fileModel = projectModel.FindFile(codeCompletionParams.FileId);
            if (fileModel == null)
            {
                throw new Exception("Specified file does not exist in this project");
            }


            // Create a TypeSystem.ICompilation that allows resolving within the project.
            var compilation = projectModel.ProjectContent.CreateCompilation();

            #region Resolve text cursor/caret location

            // The text cursor position is crucial to creating a properly-scoped type resolution context
            // so as to get relevant code completion suggestions.
            int              textCursorOffset   = 0;
            TextLocation     textCursorLocation = new TextLocation(1, 1);
            ReadOnlyDocument doc = new ReadOnlyDocument(fileModel.Content);
            try
            {
                // if line and column aren't set, we'll assume that the cursor offset/index is set
                if (codeCompletionParams.Line == 0 && codeCompletionParams.Column == 0)
                {
                    textCursorOffset = codeCompletionParams.Offset;
                    if (textCursorOffset < 0)
                    {
                        textCursorOffset = 0;
                    }
                    textCursorLocation = doc.GetLocation(textCursorOffset);
                }
                // if either line or column are invalid (i.e. <= 0), then we'll use offset 0 instead
                else if (codeCompletionParams.Line <= 0 || codeCompletionParams.Column <= 0)
                {
                    textCursorOffset = 0;
                }
                else
                {
                    textCursorLocation          = new TextLocation(codeCompletionParams.Line, codeCompletionParams.Column);
                    textCursorOffset            = doc.GetOffset(textCursorLocation);
                    codeCompletionParams.Offset = textCursorOffset;
                }
            }
            catch (Exception)
            {
                textCursorOffset   = 0;
                textCursorLocation = new TextLocation(1, 1);
            }
            finally
            {
                projectAnalysisResult.Line   = textCursorLocation.Line;
                projectAnalysisResult.Column = textCursorLocation.Column;
                projectAnalysisResult.Offset = textCursorOffset;
            }

            #endregion

            #region Create and Refine the type resolution context as much as possible based upon the cursor position

            var typeResolveContext = new CSharpTypeResolveContext(compilation.MainAssembly);
            // Constrain the resolve context by using scope
            typeResolveContext = typeResolveContext
                                 .WithUsingScope(fileModel.UnresolvedFile.GetUsingScope(textCursorLocation)
                                                 .Resolve(compilation));

            var curDef = fileModel.UnresolvedFile.GetInnermostTypeDefinition(textCursorLocation);
            if (curDef != null)
            {
                var resolvedDef = curDef.Resolve(typeResolveContext).GetDefinition();
                typeResolveContext = typeResolveContext.WithCurrentTypeDefinition(resolvedDef);
                var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= textCursorLocation && textCursorLocation < m.BodyRegion.End);
                if (curMember != null)
                {
                    typeResolveContext = typeResolveContext.WithCurrentMember(curMember);
                }
            }

            #endregion

            // The purpose of the rest of these steps is a little fuzzy in my mind...
            // I'm still trying to understand them fully and if/why they're all needed.
            // It seems there is some redundancy here...

            var completionContext = new DefaultCompletionContextProvider(doc, fileModel.UnresolvedFile);

            #region Add Preprocessor Symbols??
            completionContext.AddSymbol("TEST");
            foreach (var sym in fileModel.SyntaxTree.ConditionalSymbols)
            {
                completionContext.AddSymbol(sym);
            }
            #endregion

            var completionDataFactory = new CodeCompletionDataFactory(new CSharpResolver(typeResolveContext));

            var completionEngine = new CSharpCompletionEngine(doc, completionContext, completionDataFactory, projectModel.ProjectContent, typeResolveContext);
            completionEngine.EolMarker        = Environment.NewLine;
            completionEngine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
            projectModel.CompletionEngine     = completionEngine;

            // Attach contextual info to analysis result
            GetDocumentContext(projectAnalysisResult, textCursorOffset, doc);

            // Finally, generate completion data!
            var completionOptions = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();

            projectAnalysisResult.CompletionOptions       = completionOptions.OrderBy(x => x.CompletionText).ToArray();
            projectAnalysisResult.AutoCompleteEmptyMatch  = completionEngine.AutoCompleteEmptyMatch;
            projectAnalysisResult.AutoSelect              = completionEngine.AutoSelect;
            projectAnalysisResult.DefaultCompletionString = completionEngine.DefaultCompletionString;

            int startPos, wordLength;
            if (completionEngine.TryGetCompletionWord(textCursorOffset, out startPos, out wordLength))
            {
                //Debug.WriteLine("TryGetCompletionWord :: startpos:{0}  wordlength:{1}", startPos, wordLength);
                string completionWord = projectAnalysisResult.CompletionWord = doc.GetText(startPos, wordLength);

                if (!string.IsNullOrWhiteSpace(completionWord))
                {
                    var bestMatch = projectAnalysisResult.CompletionOptions
                                    .FirstOrDefault(x => x.CompletionText.CompareTo(completionWord) >= 0);
                    projectAnalysisResult.BestMatchToCompletionWord = bestMatch;
                    //if (bestMatch != null)
                    //projectAnalysisResult.BestMatchToCompletionWord = bestMatch.CompletionText;
                }
            }

            projectAnalysisResult.TimeElapsed = sw.Elapsed;

            return(projectAnalysisResult);
        }
Пример #11
0
        public static ProjectAnalysisResult RunFullProjectAnalysis(ProjectAnalysisRequest projectAnalysisRequest) // ProjectModel projectModel, int fileId, int line, int column)
        {
            Stopwatch sw = Stopwatch.StartNew();

            ProjectAnalysisResult projectAnalysisResult = new ProjectAnalysisResult();
            ProjectModel          projectModel          = projectAnalysisRequest.ProjectModel;


            // Set up the project (if not already done)
            if (projectModel.ProjectContent == null)
            {
                projectModel.ProjectContent = new CSharpProjectContent();
                projectModel.ProjectContent = projectModel.ProjectContent.AddAssemblyReferences(QCReferences.Value);
            }

            // For each new file, we need to integrate it into the project content
            var fileModelsInProject = projectModel.GetFileDescendants().ToArray();

            foreach (var fileModelInProject in fileModelsInProject)
            {
                IntegrateFileModel(projectModel, fileModelInProject);
            }

            // We can return now if no code completion was requested
            if (projectAnalysisRequest.CodeCompletionParameters == null)
            {
                projectAnalysisResult.TimeElapsed = sw.Elapsed;
                return(projectAnalysisResult);
            }

            // Now it's time to give attention specifically to the matter of resolving the code completion
            // options.  This, of course, requires a deeper analysis of the specified file...

            var codeCompletionParams = projectAnalysisRequest.CodeCompletionParameters;

            // Locate the file in the project
            ProjectFileModel fileModel = projectModel.FindFile(codeCompletionParams.FileId);

            if (fileModel == null)
            {
                throw new Exception("Specified file does not exist in this project");
            }


            // Create a TypeSystem.ICompilation that allows resolving within the project.
            var compilation = projectModel.ProjectContent.CreateCompilation();

            #region Resolve text cursor/caret location

            // The text cursor position is crucial to creating a properly-scoped type resolution context
            // so as to get relevant code completion suggestions.
            int              textCursorOffset;
            TextLocation     textCursorLocation;
            ReadOnlyDocument doc = new ReadOnlyDocument(fileModel.Content);
            if (codeCompletionParams.Line == 0 && codeCompletionParams.Column == 0)
            {
                textCursorOffset            = codeCompletionParams.Offset;
                textCursorLocation          = doc.GetLocation(textCursorOffset);
                codeCompletionParams.Line   = textCursorLocation.Line;
                codeCompletionParams.Column = textCursorLocation.Column;
            }
            else
            {
                textCursorLocation          = new TextLocation(codeCompletionParams.Line, codeCompletionParams.Column);
                textCursorOffset            = doc.GetOffset(textCursorLocation);
                codeCompletionParams.Offset = textCursorOffset;
            }

            #endregion

            #region Create and Refine the type resolution context as much as possible based upon the cursor position

            var typeResolveContext = new CSharpTypeResolveContext(compilation.MainAssembly);
            // Constrain the resolve context by using scope
            typeResolveContext = typeResolveContext
                                 .WithUsingScope(fileModel.UnresolvedFile.GetUsingScope(textCursorLocation)
                                                 .Resolve(compilation));

            var curDef = fileModel.UnresolvedFile.GetInnermostTypeDefinition(textCursorLocation);
            if (curDef != null)
            {
                var resolvedDef = curDef.Resolve(typeResolveContext).GetDefinition();
                typeResolveContext = typeResolveContext.WithCurrentTypeDefinition(resolvedDef);
                var curMember = resolvedDef.Members.FirstOrDefault(m => m.Region.Begin <= textCursorLocation && textCursorLocation < m.BodyRegion.End);
                if (curMember != null)
                {
                    typeResolveContext = typeResolveContext.WithCurrentMember(curMember);
                }
            }

            #endregion

            // The purpose of the rest of these steps is a little fuzzy in my mind...
            // I'm still trying to understand them fully and if/why they're all needed.
            // It seems there is some redundancy here...

            var completionContext = new DefaultCompletionContextProvider(doc, fileModel.UnresolvedFile);

            #region Add Preprocessor Symbols??
            completionContext.AddSymbol("TEST");
            foreach (var sym in fileModel.SyntaxTree.ConditionalSymbols)
            {
                completionContext.AddSymbol(sym);
            }
            #endregion

            var completionDataFactory = new TestCompletionDataFactory(new CSharpResolver(typeResolveContext));

            var completionEngine = new CSharpCompletionEngine(doc, completionContext, completionDataFactory, projectModel.ProjectContent, typeResolveContext);
            completionEngine.EolMarker        = Environment.NewLine;
            completionEngine.FormattingPolicy = FormattingOptionsFactory.CreateMono();
            projectModel.CompletionEngine     = completionEngine;

            #region Debugging Aid
            // Resolve content around text cursor
            int numberOfCharactersAroundCursorToResolve = 20;
            int firstCharOffset = textCursorOffset - numberOfCharactersAroundCursorToResolve / 2;
            if (firstCharOffset < 0)
            {
                firstCharOffset = 0;
            }
            if (doc.TextLength < firstCharOffset + numberOfCharactersAroundCursorToResolve)
            {
                numberOfCharactersAroundCursorToResolve = doc.TextLength - firstCharOffset;
            }
            string surroundingText = doc.GetText(firstCharOffset, numberOfCharactersAroundCursorToResolve);
            Debug.WriteLine("Text around cursor: [{0}]", surroundingText);
            #endregion

            // Finally, generate completion data!
            var completionOptions = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();
            projectAnalysisResult.CompletionOptions       = completionEngine.GetCompletionData(textCursorOffset, projectAnalysisRequest.CodeCompletionParameters.CtrlSpace).ToArray();
            projectAnalysisResult.AutoCompleteEmptyMatch  = completionEngine.AutoCompleteEmptyMatch;
            projectAnalysisResult.AutoSelect              = completionEngine.AutoSelect;
            projectAnalysisResult.DefaultCompletionString = completionEngine.DefaultCompletionString;

            int startPos, wordLength;
            if (completionEngine.TryGetCompletionWord(textCursorOffset, out startPos, out wordLength))
            {
                Debug.WriteLine("TryGetCompletionWord :: startpos:{0}  wordlength:{1}", startPos, wordLength);
                projectAnalysisResult.CompletionWord = doc.GetText(startPos, wordLength);
            }

            projectAnalysisResult.TimeElapsed = sw.Elapsed;

            return(projectAnalysisResult);
        }
Пример #12
0
        protected override CodeCompletionResult GetCodeCompletionResult(bool controlSpace)
        {
            var document = codeEditor.TextEditor.Document;
            int offset   = codeEditor.TextEditor.CaretOffset;
            var result   = new CodeCompletionResult();

            try {
                var completionContext = new CSharpCodeCompletionContext(document, offset, projectContent);
                var completionFactory = new CSharpCodeCompletionDataFactory(completionContext);
                var cce = new CSharpCompletionEngine(
                    completionContext.Document,
                    completionContext.CompletionContextProvider,
                    completionFactory,
                    completionContext.ProjectContent,
                    completionContext.TypeResolveContextAtCaret
                    );

                char completionChar = completionContext.Document.GetCharAt(completionContext.Offset - 1);
                int  startPos, triggerWordLength;
                IEnumerable <ICompletionData> completionData;

                if (controlSpace)
                {
                    if (!cce.TryGetCompletionWord(completionContext.Offset, out startPos, out triggerWordLength))
                    {
                        startPos          = completionContext.Offset;
                        triggerWordLength = 0;
                    }
                    completionData = cce.GetCompletionData(startPos, true);
                }
                else
                {
                    startPos = completionContext.Offset;
                    if (char.IsLetterOrDigit(completionChar) || completionChar == '_')
                    {
                        if (startPos > 1 && char.IsLetterOrDigit(completionContext.Document.GetCharAt((startPos - 2))))
                        {
                            return(result);
                        }
                        completionData    = cce.GetCompletionData(startPos, false);
                        triggerWordLength = 1;
                    }
                    else
                    {
                        completionData    = cce.GetCompletionData(startPos, false);
                        triggerWordLength = 0;
                    }
                }

                result.TriggerWordLength = triggerWordLength;
                result.TriggerWord       = completionContext.Document.GetText(completionContext.Offset - triggerWordLength, triggerWordLength);

                if (completionData.Any() && cce.AutoCompleteEmptyMatch)
                {
                    foreach (var completion in completionData)
                    {
                        var cast = completion as CompletionData;
                        if (cast != null)
                        {
                            cast.TriggerWord       = result.TriggerWord;
                            cast.TriggerWordLength = result.TriggerWordLength;
                            result.CompletionData.Add(cast);
                        }
                    }
                }

                if (!controlSpace)
                {
                    var pce = new CSharpParameterCompletionEngine(
                        completionContext.Document,
                        completionContext.CompletionContextProvider,
                        completionFactory,
                        completionContext.ProjectContent,
                        completionContext.TypeResolveContextAtCaret
                        );

                    var parameterDataProvider = pce.GetParameterDataProvider(completionContext.Offset, completionChar);
                    result.OverloadProvider = parameterDataProvider as IUpdatableOverloadProvider;
                }
            } catch {
                // ignore exceptions thrown during code completion
            }

            return(result);
        }
        ICompletionDataList InternalHandleCodeCompletion(CodeCompletionContext completionContext, char completionChar, bool ctrlSpace, ref int triggerWordLength)
        {
            var data = TextEditorData;

            if (data.CurrentMode is TextLinkEditMode)
            {
                if (((TextLinkEditMode)data.CurrentMode).TextLinkMode == TextLinkMode.EditIdentifier)
                {
                    return(null);
                }
            }
            if (Unit == null || CSharpUnresolvedFile == null)
            {
                return(null);
            }
            if (typeSystemSegmentTree == null)
            {
                return(null);
            }

            var list = new CSharpCompletionDataList();

            list.Resolver = CSharpUnresolvedFile != null?CSharpUnresolvedFile.GetResolver(UnresolvedFileCompilation, Document.Editor.Caret.Location) : new CSharpResolver(Compilation);

            var ctx = CSharpUnresolvedFile.GetTypeResolveContext(UnresolvedFileCompilation, data.Caret.Location) as CSharpTypeResolveContext;

            var engine = new CSharpCompletionEngine(
                data.Document,
                typeSystemSegmentTree,
                new CompletionDataFactory(this, new CSharpResolver(ctx)),
                Document.GetProjectContext(),
                ctx
                );

            if (Document.HasProject)
            {
                var configuration = Document.Project.GetConfiguration(MonoDevelop.Ide.IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration;
                var par           = configuration != null ? configuration.CompilationParameters as PlayScriptCompilerParameters : null;
                if (par != null)
                {
                    engine.LanguageVersion = MonoDevelop.PlayScript.Parser.TypeSystemParser.ConvertLanguageVersion(par.LangVersion);
                }
            }

            engine.FormattingPolicy = FormattingPolicy.CreateOptions();
            engine.EolMarker        = data.EolMarker;
            engine.IndentString     = data.Options.IndentationString;
            try {
                foreach (var cd in engine.GetCompletionData(completionContext.TriggerOffset, ctrlSpace))
                {
                    list.Add(cd);
                    if (cd is IListData)
                    {
                        ((IListData)cd).List = list;
                    }
                }
            } catch (Exception e) {
                LoggingService.LogError("Error while getting completion data.", e);
            }
            list.AutoCompleteEmptyMatch             = engine.AutoCompleteEmptyMatch;
            list.AutoCompleteEmptyMatchOnCurlyBrace = engine.AutoCompleteEmptyMatchOnCurlyBracket;
            list.AutoSelect = engine.AutoSelect;
            list.DefaultCompletionString = engine.DefaultCompletionString;
            list.CloseOnSquareBrackets   = engine.CloseOnSquareBrackets;
            if (ctrlSpace)
            {
                list.AutoCompleteUniqueMatch = true;
            }
            return(list.Count > 0 ? list : null);
        }