Пример #1
0
        public ResolveResult ResolveAtLocation(TextLocation location, CancellationToken cancellationToken = default(CancellationToken))
        {
            int offset = textDocument.GetOffset(location);
            var line   = textDocument.GetLineByNumber(location.Line);

            if (offset == line.EndOffset)
            {
                return(ErrorResolveResult.UnknownError);
            }
            if (char.IsWhiteSpace(textDocument.GetCharAt(offset)))
            {
                return(ErrorResolveResult.UnknownError);
            }

            AXmlObject innermost = parseInfo.Document.GetChildAtOffset(offset);

            if (innermost is AXmlText)
            {
                return(ResolveText((AXmlText)innermost, cancellationToken));
            }
            if (innermost is AXmlTag)
            {
                return(ResolveTag((AXmlTag)innermost, cancellationToken));
            }
            if (innermost is AXmlElement)
            {
                return(ResolveElement((AXmlElement)innermost, cancellationToken));
            }
            if (innermost is AXmlAttribute)
            {
                return(ResolveAttribute((AXmlAttribute)innermost, offset, cancellationToken));
            }
            return(ErrorResolveResult.UnknownError);
        }
Пример #2
0
        private void AddInsertion(AstNode node, Phrase phrase)
        {
            // start tag
            Insertions.Add(new Insertion
            {
                Offset = Document.GetOffset(node.StartLocation),
                Phrase = String.Format("<span class='{0}'>", phrase.ToCss())
            });

            // end tag
            Insertions.Add(new Insertion
            {
                Offset = Document.GetOffset(node.EndLocation),
                Phrase = "</span>"
            });
        }
Пример #3
0
        void CheckWhitespace(AstNode startNode, TextLocation whitespaceStart, AstNode endNode, TextLocation whitespaceEnd)
        {
            if (whitespaceStart == whitespaceEnd || startNode == endNode)
            {
                return;
            }
            int    start     = currentDocument.GetOffset(whitespaceStart.Line, whitespaceStart.Column);
            int    end       = currentDocument.GetOffset(whitespaceEnd.Line, whitespaceEnd.Column);
            string text      = currentDocument.GetText(start, end - start);
            bool   assertion = string.IsNullOrWhiteSpace(text);

            if (!assertion)
            {
                if (startNode.Parent != endNode.Parent)
                {
                    PrintNode(startNode.Parent);
                }
                PrintNode(endNode.Parent);
            }
            Assert.IsTrue(assertion, "Expected whitespace between " + startNode.GetType() + ":" + whitespaceStart + " and " + endNode.GetType() + ":" + whitespaceEnd
                          + ", but got '" + text + "' (in " + currentFileName + " parent:" + startNode.Parent.GetType() + ")");
        }
Пример #4
0
        void CollectMembers(string code, string memberName, bool includeOverloads = true)
        {
            StringBuilder sb      = new StringBuilder();
            List <int>    offsets = new List <int>();

            foreach (var ch in code)
            {
                if (ch == '$')
                {
                    offsets.Add(sb.Length);
                    continue;
                }
                sb.Append(ch);
            }
            var syntaxTree     = SyntaxTree.Parse(sb.ToString(), "test.cs");
            var unresolvedFile = syntaxTree.ToTypeSystem();
            var compilation    = TypeSystemHelper.CreateCompilation(unresolvedFile);

            var symbol = FindReferencesTest.GetSymbol(compilation, memberName);
            var col    = new SymbolCollector();

            col.IncludeOverloads = includeOverloads;
            col.GroupForRenaming = true;

            var result = col.GetRelatedSymbols(new Lazy <TypeGraph>(() => new TypeGraph(compilation.Assemblies)),
                                               symbol);

            if (offsets.Count != result.Count())
            {
                foreach (var a in result)
                {
                    Console.WriteLine(a);
                }
            }
            Assert.AreEqual(offsets.Count, result.Count());
            var doc = new ReadOnlyDocument(sb.ToString());

            result
            .Select(r => doc.GetOffset((r as IEntity).Region.Begin))
            .SequenceEqual(offsets);
        }
Пример #5
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));
        }
Пример #6
0
        void InsertEventHandlerInternal(string methodName, IEvent evt)
        {
            CSharpCodeGenerator generator = new CSharpCodeGenerator();
            var primary    = loader.GetPrimaryTypeDefinition();
            var evtHandler = primary.GetMethods(m => m.Name == methodName, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();

            if (evtHandler == null)
            {
                var insertionType = GeneralOptionsPanel.InsertTodoComment ? InsertEventHandlerBodyKind.TodoComment : InsertEventHandlerBodyKind.Nothing;
                generator.InsertEventHandler(primary, methodName, evt, true, insertionType);
            }
            else
            {
                CSharpBinding.Parser.CSharpFullParseInformation parseInfo;
                var node              = evtHandler.GetDeclaration(out parseInfo) as MethodDeclaration;
                var fileName          = new FileName(evtHandler.Region.FileName);
                var fileContentFinder = new ParseableFileContentFinder();

                if (node != null && !node.Body.IsNull)
                {
                    var location       = node.Body.FirstChild.StartLocation;
                    var firstStatement = node.Body.Children.OfType <Statement>().FirstOrDefault();

                    if (firstStatement == null)
                    {
                        var fileContent = fileContentFinder.Create(fileName);
                        var document    = new ReadOnlyDocument(fileContent);
                        var offset      = document.GetOffset(new TextLocation(location.Line + 1, 1));
                        var length      = DocumentUtilities.GetWhitespaceAfter(fileContent, offset).Length;
                        location = new TextLocation(location.Line + 1, length + 1);
                    }
                    else
                    {
                        location = firstStatement.StartLocation;
                    }
                    SD.FileService.JumpToFilePosition(fileName, location.Line, location.Column);
                }
            }
        }
Пример #7
0
        void TestRename(string code, string symbolName)
        {
            StringBuilder sb      = new StringBuilder();
            List <int>    offsets = new List <int>();

            foreach (var ch in code)
            {
                if (ch == '$')
                {
                    offsets.Add(sb.Length);
                    continue;
                }
                sb.Append(ch);
            }
            Init(sb.ToString());
            findReferences.WholeVirtualSlot = true;
            var doc    = new ReadOnlyDocument(sb.ToString());
            var result = Rename(symbolName, "x", false);

            Assert.AreEqual(offsets.Count, result.Count);

            result.Select(r => doc.GetOffset(r.StartLocation)).SequenceEqual(offsets);
        }
        //// 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);
        }
Пример #9
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);
        }