コード例 #1
0
        private static void AssertNoExpr(PythonAstAndSource astAndSource, int startLine, int startColumn, int endLine, int endColumn)
        {
            var ast     = astAndSource.Ast;
            var code    = astAndSource.Source;
            var options = astAndSource.Options;

            int start       = ast.LocationToIndex(new SourceLocation(startLine, 1));
            int end         = ast.LocationToIndex(new SourceLocation(endLine + 1, 1));
            var fullLine    = code.Substring(start);
            int lastNewline = Environment.NewLine.Select(c => fullLine.LastIndexOf(c, end - start - 1)).Where(i => i > 0).DefaultIfEmpty(-1).Min();

            if (lastNewline > 0)
            {
                fullLine = fullLine.Remove(lastNewline);
            }

            var finder = new ExpressionFinder(ast, options);
            var range  = new SourceSpan(new SourceLocation(startLine, startColumn), new SourceLocation(endLine, endColumn));
            var span   = finder.GetExpressionSpan(range);

            if (span == null || span.Value.Start == span.Value.End)
            {
                return;
            }

            start = ast.LocationToIndex(span.Value.Start);
            end   = ast.LocationToIndex(span.Value.End);
            var actual = code.Substring(start, end - start);

            Assert.Fail($"Found unexpected expression <{actual}> at from {range} at {span.Value} in <{fullLine}>");
        }
コード例 #2
0
        public static void FindExpression(PythonAst ast, SourceLocation position, FindExpressionOptions options, out Node expression, out Node statement, out ScopeStatement scope)
        {
            expression = null;
            statement  = null;
            scope      = null;

            if (ast == null)
            {
                return;
            }

            var finder = new ExpressionFinder(ast, options);

            var index = ast.LocationToIndex(position);

            finder.Get(index, index, out expression, out statement, out scope);

            var col = position.Column;

            while (CanBackUp(ast, expression, statement, scope, col))
            {
                col   -= 1;
                index -= 1;
                finder.Get(index, index, out expression, out statement, out scope);
            }

            expression = expression ?? (statement as ExpressionStatement)?.Expression;
        }
コード例 #3
0
            public static bool Find(Expression expression, Predicate <Expression> predicate)
            {
                var f = new ExpressionFinder(predicate);

                f.Visit(expression);
                return(f.Found);
            }
コード例 #4
0
        public override bool IsValid(Expression expression)
        {
            _expressionFinder = new ExpressionFinder(this);
            _expressionFinder.Visit(expression);

            return(_expressionFinder.FoundExpressions.Any());
        }
コード例 #5
0
        private static void AssertExpr(PythonAstAndSource astAndSource, int startLine, int startColumn, int endLine, int endColumn, string expected)
        {
            var ast     = astAndSource.Ast;
            var code    = astAndSource.Source;
            var options = astAndSource.Options;

            int start       = ast.LocationToIndex(new SourceLocation(startLine, 1));
            int end         = ast.LocationToIndex(new SourceLocation(endLine + 1, 1));
            var fullLine    = code.Substring(start);
            int lastNewline = Environment.NewLine.Select(c => fullLine.LastIndexOf(c, end - start - 1)).Where(i => i > 0).DefaultIfEmpty(-1).Min();

            if (lastNewline > 0)
            {
                fullLine = fullLine.Remove(lastNewline);
            }

            var finder = new ExpressionFinder(ast, options);
            var range  = new SourceSpan(new SourceLocation(startLine, startColumn), new SourceLocation(endLine, endColumn));
            var span   = finder.GetExpressionSpan(range);

            Assert.IsNotNull(span, $"Did not find any expression at {range} in <{fullLine}>");

            start = ast.LocationToIndex(span.Value.Start);
            end   = ast.LocationToIndex(span.Value.End);
            var actual = code.Substring(start, end - start);

            Assert.AreEqual(expected, actual, $"Mismatched expression from {range} at {span.Value} in <{fullLine}>");
        }
コード例 #6
0
        internal SnapshotSpan?GetExpressionAtPointWorker(SnapshotSpan span, GetExpressionOptions options)
        {
            // First do some very quick tokenization to save a full analysis
            if (!IsPossibleExpressionAtPoint(span.Start))
            {
                return(null);
            }

            if (span.End.GetContainingLine() != span.Start.GetContainingLine() &&
                !IsPossibleExpressionAtPoint(span.End))
            {
                return(null);
            }

            var sourceSpan = new SnapshotSpanSourceCodeReader(
                new SnapshotSpan(span.Snapshot, 0, span.End.Position)
                );

            PythonAst ast;

            using (var parser = Parser.CreateParser(sourceSpan, LanguageVersion)) {
                ast = parser.ParseFile();
            }

            var finder     = new ExpressionFinder(ast, options);
            var actualExpr = finder.GetExpressionSpan(span.ToSourceSpan());

            return(actualExpr?.ToSnapshotSpan(span.Snapshot));
        }
コード例 #7
0
        public void Test004()
        {
            var xfr = new ExpressionFinder();
            var needle = Expression.Parameter(typeof(int));
            var haystack = default(Expression);

            Assert.IsFalse(xfr.Exists(needle, haystack));
        }
コード例 #8
0
        public void Test004()
        {
            var xfr      = new ExpressionFinder();
            var needle   = Expression.Parameter(typeof(int));
            var haystack = default(Expression);

            Assert.IsFalse(xfr.Exists(needle, haystack));
        }
コード例 #9
0
        public void Test002()
        {
            var xfr = new ExpressionFinder();
            var needle = Expression.Parameter(typeof(int));
            var haystack = Expression.Add(
                Expression.Add(Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int))),
                Expression.Multiply(Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)))
            );

            Assert.IsFalse(xfr.Exists(needle, haystack));
        }
コード例 #10
0
        public override bool IsValid(Expression expression)
        {
            _expressionFinder = new ExpressionFinder(this);
            if (IsQueryableResult(expression))
            {
                _expressionFinder.TryAddType(expression.Type.GetGenericArguments()[0]);
                _expressionFinder.Visit(expression);
            }

            return(_expressionFinder.FoundExpressions.Any());
        }
コード例 #11
0
        public void Test002()
        {
            var xfr      = new ExpressionFinder();
            var needle   = Expression.Parameter(typeof(int));
            var haystack = Expression.Add(
                Expression.Add(Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int))),
                Expression.Multiply(Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)))
                );

            Assert.IsFalse(xfr.Exists(needle, haystack));
        }
コード例 #12
0
ファイル: CompletionAnalysis.cs プロジェクト: HopeIsaGth/PTVS
        private IEnumerable <CompletionItem> GetCompletionsFromMembers(ref GetMemberOptions opts)
        {
            var finder = new ExpressionFinder(Tree, GetExpressionOptions.EvaluateMembers);

            if (finder.GetExpression(Index) is Expression expr)
            {
                _log.TraceMessage($"Completing expression {expr.ToCodeString(Tree, CodeFormattingOptions.Traditional)}");
                ParentExpression = expr;
                return(Analysis.GetMembers(expr, Position, opts, null).Select(ToCompletionItem));
            }
            return(null);
        }
コード例 #13
0
        private IEnumerable <CompletionItem> GetCompletionsFromTopLevel(bool allowKeywords, bool allowArguments, GetMemberOptions opts)
        {
            if (Node?.EndIndex < Index)
            {
                return(Empty);
            }

            if (allowKeywords)
            {
                opts |= GetMemberOptions.IncludeExpressionKeywords;
                if (ShouldIncludeStatementKeywords(Statement, Index, out var span))
                {
                    opts |= GetMemberOptions.IncludeStatementKeywords;
                    if (span.HasValue)
                    {
                        ApplicableSpan = new SourceSpan(
                            Tree.IndexToLocation(span.Value.Start),
                            Tree.IndexToLocation(span.Value.End)
                            );
                    }
                }
                ShouldAllowSnippets = true;
            }

            _log.TraceMessage($"Completing all names");
            var members = Analysis.GetAllAvailableMembers(Position, opts);

            if (allowArguments)
            {
                var finder = new ExpressionFinder(Tree, new GetExpressionOptions {
                    Calls = true
                });
                if (finder.GetExpression(Index) is CallExpression callExpr &&
                    callExpr.GetArgumentAtIndex(Tree, Index, out _))
                {
                    var argNames = Analysis.GetSignatures(callExpr.Target, Position)
                                   .SelectMany(o => o.Parameters).Select(p => p?.Name)
                                   .Where(n => !string.IsNullOrEmpty(n))
                                   .Distinct()
                                   .Except(callExpr.Args.MaybeEnumerate().Select(a => a.Name).Where(n => !string.IsNullOrEmpty(n)))
                                   .Select(n => new MemberResult($"{n}=", PythonMemberType.NamedArgument));

                    argNames = argNames.MaybeEnumerate().ToArray();
                    _log.TraceMessage($"Including {argNames.Count()} named arguments");

                    members = members?.Concat(argNames) ?? argNames;
                }
            }

            return(members.Select(ToCompletionItem).Where(c => !string.IsNullOrEmpty(c.insertText)));
        }
コード例 #14
0
        public UniqueNameGenerator(IDocumentAnalysis analysis, int position)
        {
            _analysis       = analysis;
            _uniqueInModule = position < 0;

            if (!_uniqueInModule)
            {
                var finder = new ExpressionFinder(analysis.Ast, new FindExpressionOptions()
                {
                    Names = true
                });
                finder.Get(position, position, out _, out _, out _scope);
            }
        }
コード例 #15
0
        static int GetArgumentIndex(ITextEditor editor)
        {
            ILexer           lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, editor.Document.CreateReader());
            ExpressionFinder ef    = new ExpressionFinder();

            Token t = lexer.NextToken();

            while (t.Kind != Tokens.EOF && t.Location < editor.Caret.Position)
            {
                ef.InformToken(t);
                t = lexer.NextToken();
            }

            return(ef.ActiveArgument);
        }
        public async Task <IEnumerable <CodeAction> > GetCodeActionsAsync(IDocumentAnalysis analysis, CodeActionSettings settings, DiagnosticsEntry diagnostic, CancellationToken cancellationToken)
        {
            if (!settings.GetQuickFixOption("addimports", true))
            {
                return(Enumerable.Empty <CodeAction>());
            }

            var finder = new ExpressionFinder(analysis.Ast, new FindExpressionOptions()
            {
                Names = true
            });
            var node = finder.GetExpression(diagnostic.SourceSpan);

            if (!(node is NameExpression nex))
            {
                return(Enumerable.Empty <CodeAction>());
            }

            var identifier = nex.Name;

            if (string.IsNullOrEmpty(identifier))
            {
                return(Enumerable.Empty <CodeAction>());
            }

            var codeActions = new List <CodeAction>();
            var diagnostics = new[] { diagnostic.ToDiagnostic() };

            // see whether it is one of abbreviation we specialize
            foreach (var moduleFullName in WellKnownAbbreviationMap.Where(kv => kv.Value == identifier).Select(kv => kv.Key))
            {
                var moduleName = GetModuleName(moduleFullName);

                await GetCodeActionsAsync(analysis, diagnostics, new Input(node, moduleName, moduleFullName), codeActions, cancellationToken);
            }

            // add then search given name as it is
            await GetCodeActionsAsync(analysis, diagnostics, new Input(node, identifier), codeActions, cancellationToken);

            return(codeActions);

            string GetModuleName(string moduleFullName)
            {
                var index = moduleFullName.LastIndexOf(".");

                return(index < 0 ? moduleFullName : moduleFullName.Substring(index + 1));
            }
        }
コード例 #17
0
        public CompletionAnalysis(
            IModuleAnalysis analysis,
            PythonAst tree,
            SourceLocation position,
            GetMemberOptions opts,
            ServerSettings.PythonCompletionOptions completionSettings,
            DocumentationBuilder textBuilder,
            ILogger log,
            Func <TextReader> openDocument
            )
        {
            Analysis      = analysis ?? throw new ArgumentNullException(nameof(analysis));
            Tree          = tree ?? throw new ArgumentNullException(nameof(tree));
            Position      = position;
            Index         = Tree.LocationToIndex(Position);
            Options       = opts;
            _pathResolver = analysis.ProjectState.CurrentPathResolver;
            _textBuilder  = textBuilder;
            _log          = log;
            _openDocument = openDocument;
            _addBrackets  = completionSettings.addBrackets;

            var finder = new ExpressionFinder(Tree, new GetExpressionOptions {
                Names              = true,
                Members            = true,
                NamedArgumentNames = true,
                ImportNames        = true,
                ImportAsNames      = true,
                Literals           = true,
                Errors             = true
            });

            finder.Get(Index, Index, out var node, out _statement, out _scope);

            var index = Index;
            var col   = Position.Column;

            while (CanBackUp(Tree, node, _statement, _scope, col))
            {
                col   -= 1;
                index -= 1;
                finder.Get(index, index, out node, out _statement, out _scope);
            }

            Node = node ?? (_statement as ExpressionStatement)?.Expression;
        }
コード例 #18
0
        void RunTest(string code, string expectedOutput)
        {
            ExpressionFinder p     = new ExpressionFinder();
            ILexer           lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(code));
            Token            t;

            do
            {
                t = lexer.NextToken();
                p.InformToken(t);
            } while (t.Kind != VBParser.Tokens.EOF);

            Console.WriteLine(p.Output);

            Assert.IsEmpty(p.Errors);

            Assert.AreEqual(expectedOutput, p.Output);
        }
コード例 #19
0
        void RunTest(string code, string expectedOutput)
        {
            ExpressionFinder p     = new ExpressionFinder();
            VBLexer          lexer = new VBLexer(new StringReader(code));
            Token            t;

            do
            {
                t = lexer.NextToken();
                p.InformToken(t);
            } while (t.Kind != Tokens.EOF);

            Console.WriteLine(p.Output);

            Assert.IsEmpty(p.Errors);

            Assert.AreEqual(expectedOutput, p.Output);
        }
コード例 #20
0
        public CompletionAnalysis(ModuleAnalysis analysis, PythonAst tree, SourceLocation position, GetMemberOptions opts, Action <FormattableString> trace)
        {
            Analysis = analysis ?? throw new ArgumentNullException(nameof(analysis));
            Tree     = tree ?? throw new ArgumentNullException(nameof(tree));
            Position = position;
            Index    = Tree.LocationToIndex(Position);
            Options  = opts;
            _trace   = trace;

            var finder = new ExpressionFinder(Tree, new GetExpressionOptions {
                Names              = true,
                MemberName         = true,
                NamedArgumentNames = true,
                ImportNames        = true,
                ImportAsNames      = true,
                Literals           = true,
            });

            finder.Get(Index, Index, out _node, out _statement, out _scope);
        }
コード例 #21
0
ファイル: CompletionAnalysis.cs プロジェクト: HopeIsaGth/PTVS
        public CompletionAnalysis(ModuleAnalysis analysis, PythonAst tree, SourceLocation position, GetMemberOptions opts, DocumentationBuilder textBuilder, ILogger log)
        {
            Analysis     = analysis ?? throw new ArgumentNullException(nameof(analysis));
            Tree         = tree ?? throw new ArgumentNullException(nameof(tree));
            Position     = position;
            Index        = Tree.LocationToIndex(Position);
            Options      = opts;
            _textBuilder = textBuilder;
            _log         = log;

            var finder = new ExpressionFinder(Tree, new GetExpressionOptions {
                Names              = true,
                MemberName         = true,
                NamedArgumentNames = true,
                ImportNames        = true,
                ImportAsNames      = true,
                Literals           = true,
            });

            finder.Get(Index, Index, out _node, out _statement, out _scope);
        }
コード例 #22
0
ファイル: CompletionAnalysis.cs プロジェクト: lmoshood/PTVS
        public CompletionAnalysis(
            ModuleAnalysis analysis,
            PythonAst tree,
            SourceLocation position,
            GetMemberOptions opts,
            DocumentationBuilder textBuilder,
            ILogger log
            )
        {
            Analysis     = analysis ?? throw new ArgumentNullException(nameof(analysis));
            Tree         = tree ?? throw new ArgumentNullException(nameof(tree));
            Position     = position;
            Index        = Tree.LocationToIndex(Position);
            Options      = opts;
            _textBuilder = textBuilder;
            _log         = log;

            var finder = new ExpressionFinder(Tree, new GetExpressionOptions {
                Names              = true,
                Members            = true,
                NamedArgumentNames = true,
                ImportNames        = true,
                ImportAsNames      = true,
                Literals           = true,
            });

            finder.Get(Index, Index, out _node, out _statement, out _scope);

            int index = Index;
            int col   = Position.Column;

            while (CanBackUp(Tree, _node, _statement, _scope, col))
            {
                col   -= 1;
                index -= 1;
                finder.Get(index, index, out _node, out _statement, out _scope);
            }

            _node = _node ?? (_statement as ExpressionStatement)?.Expression;
        }
コード例 #23
0
ファイル: Server.Hover.cs プロジェクト: xing2fan/PTVS
        public override async Task <Hover> Hover(TextDocumentPositionParams @params)
        {
            await _analyzerCreationTask;

            await IfTestWaitForAnalysisCompleteAsync();

            var uri = @params.textDocument.uri;

            _projectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"Hover in {uri} at {@params.position}");

            var analysis = entry?.Analysis;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(EmptyHover);
            }

            tree = GetParseTree(entry, uri, CancellationToken, out var version) ?? tree;

            var index = tree.LocationToIndex(@params.position);
            var w     = new ImportedModuleNameWalker(entry.ModuleName, index);

            tree.Walk(w);
            if (!string.IsNullOrEmpty(w.ImportedName) &&
                _analyzer.Modules.TryImport(w.ImportedName, out var modRef))
            {
                var doc = _displayTextBuilder.GetModuleDocumentation(modRef);
                return(new Hover {
                    contents = doc
                });
            }

            Expression expr;
            SourceSpan?exprSpan;

            Analyzer.InterpreterScope scope = null;

            var finder = new ExpressionFinder(tree, GetExpressionOptions.Hover);

            expr     = finder.GetExpression(@params.position) as Expression;
            exprSpan = expr?.GetSpan(tree);

            if (expr == null)
            {
                TraceMessage($"No hover info found in {uri} at {@params.position}");
                return(EmptyHover);
            }

            TraceMessage($"Getting hover for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");
            var values = analysis.GetValues(expr, @params.position, scope).ToList();

            string originalExpr;

            if (expr is ConstantExpression || expr is ErrorExpression)
            {
                originalExpr = null;
            }
            else
            {
                originalExpr = @params._expr?.Trim();
                if (string.IsNullOrEmpty(originalExpr))
                {
                    originalExpr = expr.ToCodeString(tree, CodeFormattingOptions.Traditional);
                }
            }

            var names = values.Select(GetFullTypeName).Where(n => !string.IsNullOrEmpty(n)).Distinct().ToArray();

            var res = new Hover {
                contents = GetMarkupContent(
                    _displayTextBuilder.GetDocumentation(values, originalExpr),
                    _clientCaps.textDocument?.hover?.contentFormat),
                range      = exprSpan,
                _version   = version,
                _typeNames = names
            };

            return(res);
        }
コード例 #24
0
 /// <summary>
 /// Finds an expression before the current offset.
 /// </summary>
 public ExpressionResult FindExpression(int offset)
 {
     return(ExpressionFinder.FindExpression(TextContent, offset));
 }
コード例 #25
0
        public override async Task <SignatureHelp> SignatureHelp(TextDocumentPositionParams @params)
        {
            var uri = @params.textDocument.uri;

            ProjectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"Signatures in {uri} at {@params.position}");

            var analysis = entry != null ? await entry.GetAnalysisAsync(waitingTimeout : 50) : null;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(new SignatureHelp());
            }

            IEnumerable <IOverloadResult> overloads;
            int activeSignature = -1, activeParameter = -1;

            if (!string.IsNullOrEmpty(@params._expr))
            {
                TraceMessage($"Getting signatures for {@params._expr}");
                overloads = analysis.GetSignatures(@params._expr, @params.position);
            }
            else
            {
                var finder = new ExpressionFinder(tree, new GetExpressionOptions {
                    Calls = true
                });
                var index = tree.LocationToIndex(@params.position);
                if (finder.GetExpression(@params.position) is CallExpression callExpr)
                {
                    TraceMessage($"Getting signatures for {callExpr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");
                    overloads       = analysis.GetSignatures(callExpr.Target, @params.position);
                    activeParameter = -1;
                    if (callExpr.GetArgumentAtIndex(tree, index, out activeParameter) && activeParameter < 0)
                    {
                        // Returned 'true' and activeParameter == -1 means that we are after
                        // the trailing comma, so assume partially typed expression such as 'pow(x, y, |)
                        activeParameter = callExpr.Args.Count;
                    }
                }
                else
                {
                    TraceMessage($"No signatures found in {uri} at {@params.position}");
                    return(new SignatureHelp());
                }
            }

            var sigs = overloads.Select(ToSignatureInformation).ToArray();

            if (activeParameter >= 0 && activeSignature < 0)
            {
                // TODO: Better selection of active signature
                activeSignature = sigs
                                  .Select((s, i) => Tuple.Create(s, i))
                                  .OrderBy(t => t.Item1.parameters.Length)
                                  .FirstOrDefault(t => t.Item1.parameters.Length > activeParameter)
                                  ?.Item2 ?? -1;
            }

            activeSignature = activeSignature >= 0
                ? activeSignature
                : (sigs.Length > 0 ? 0 : -1);

            return(new SignatureHelp {
                signatures = sigs,
                activeSignature = activeSignature,
                activeParameter = activeParameter
            });
        }
コード例 #26
0
        public ExpressionResult FindFullExpression(string text, int offset)
        {
            Init(text, offset);

            ExpressionFinder p = new ExpressionFinder();

            lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(text));
            Token t;

            Block block = Block.Default;

            var expressionDelimiters = new[] { Tokens.EOL, Tokens.Colon, Tokens.Dot, Tokens.TripleDot, Tokens.DotAt };

            while (true)
            {
                t = lexer.NextToken();
                p.InformToken(t);

                if (block == Block.Default && t.EndLocation > targetPosition)
                {
                    block = p.CurrentBlock;
                }
                if (block != Block.Default && (block.isClosed || expressionDelimiters.Contains(t.Kind) && block == p.CurrentBlock))
                {
                    break;
                }
                if (t.Kind == Tokens.EOF)
                {
                    break;
                }
            }

            if (p.Errors.Any())
            {
                foreach (var e in p.Errors)
                {
                    LoggingService.Warn("not expected: " + e);
                }
            }

            BitArray expectedSet;

            try {
                expectedSet = p.GetExpectedSet();
            } catch (InvalidOperationException) {
                expectedSet = null;
            }

            int tokenOffset;

            if (t == null || t.Kind == Tokens.EOF)
            {
                tokenOffset = text.Length;
            }
            else
            {
                tokenOffset = LocationToOffset(t.Location);
            }

            int lastExpressionStartOffset = LocationToOffset(block.lastExpressionStart);

            if (lastExpressionStartOffset >= 0)
            {
                if (offset < tokenOffset)
                {
                    // offset is in front of this token
                    return(MakeResult(text, lastExpressionStartOffset, tokenOffset, GetContext(block), expectedSet));
                }
                else
                {
                    // offset is IN this token
                    return(MakeResult(text, lastExpressionStartOffset, offset, GetContext(block), expectedSet));
                }
            }
            else
            {
                return(new ExpressionResult(null, GetContext(block)));
            }
        }
コード例 #27
0
        public override async Task <Reference[]> FindReferences(ReferencesParams @params, CancellationToken cancellationToken)
        {
            await WaitForCompleteAnalysisAsync(cancellationToken);

            var uri = @params.textDocument.uri;

            ProjectFiles.GetEntry(@params.textDocument, @params._version, out var entry, out var tree);

            TraceMessage($"References in {uri} at {@params.position}");

            var analysis = entry != null ? await entry.GetAnalysisAsync(50, cancellationToken) : null;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(Array.Empty <Reference>());
            }

            tree = GetParseTree(entry, uri, cancellationToken, out var version);
            var modRefs = GetModuleReferences(entry, tree, version, @params);

            IEnumerable <IAnalysisVariable> result;

            if (!string.IsNullOrEmpty(@params._expr))
            {
                TraceMessage($"Getting references for {@params._expr}");
                result = analysis.GetVariables(@params._expr, @params.position);
            }
            else
            {
                var finder = new ExpressionFinder(tree, GetExpressionOptions.FindDefinition);
                if (finder.GetExpression(@params.position) is Expression expr)
                {
                    TraceMessage($"Getting references for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");
                    result = analysis.GetVariables(expr, @params.position);
                }
                else
                {
                    TraceMessage($"No references found in {uri} at {@params.position}");
                    result = Enumerable.Empty <IAnalysisVariable>();
                }
            }

            var filtered = result.Where(v => v.Type != VariableType.None);

            if (!(@params.context?.includeDeclaration ?? false))
            {
                filtered = filtered.Where(v => v.Type != VariableType.Definition);
            }
            if (!(@params.context?._includeValues ?? false))
            {
                filtered = filtered.Where(v => v.Type != VariableType.Value);
            }

            var res = filtered.Select(v => new Reference {
                uri      = v.Location.DocumentUri,
                range    = v.Location.Span,
                _kind    = ToReferenceKind(v.Type),
                _version = version?.Version
            })
                      .Concat(modRefs)
                      .GroupBy(r => r, ReferenceComparer.Instance)
                      .Select(g => g.OrderByDescending(r => (SourceLocation)r.range.end).ThenBy(r => (int?)r._kind ?? int.MaxValue).First())
                      .ToArray();

            return(res);
        }
コード例 #28
0
        public static CompletionResult GetCompletions(Node statement, ScopeStatement scopeStatement, CompletionContext context)
        {
            SourceSpan?applicableSpan = null;
            var        eval           = context.Analysis.ExpressionEvaluator;

            var options = GetOptions(statement, context.Position, out var span);

            if (span.HasValue)
            {
                applicableSpan = new SourceSpan(context.IndexToLocation(span.Value.Start), context.IndexToLocation(span.Value.End));
            }

            var scope = context.Analysis.FindScope(context.Location);
            IEnumerable <CompletionItem> items;

            using (eval.OpenScope(scope)) {
                // Get variables declared in the module.
                var variables = eval.CurrentScope.EnumerateTowardsGlobal.SelectMany(s => s.Variables).ToArray();
                items = variables.Select(v => context.ItemSource.CreateCompletionItem(v.Name, v)).ToArray();
            }

            // Get builtins
            var builtins     = context.Analysis.Document.Interpreter.ModuleResolution.BuiltinsModule;
            var builtinItems = builtins.GetMemberNames()
                               .Select(n => {
                var m = builtins.GetMember(n);
                if ((options & CompletionListOptions.ExceptionsOnly) == CompletionListOptions.ExceptionsOnly && !IsExceptionType(m.GetPythonType()))
                {
                    return(null);
                }
                return(context.ItemSource.CreateCompletionItem(n, m));
            }).ExcludeDefault();

            items = items.Concat(builtinItems);

            // Add possible function arguments.
            var finder = new ExpressionFinder(context.Ast, new FindExpressionOptions {
                Calls = true
            });

            if (finder.GetExpression(context.Position) is CallExpression callExpr && callExpr.GetArgumentAtIndex(context.Ast, context.Position, out _))
            {
                var value = eval.GetValueFromExpression(callExpr.Target);
                if (value?.GetPythonType() is IPythonFunctionType ft)
                {
                    var arguments = ft.Overloads.SelectMany(o => o.Parameters).Select(p => p?.Name)
                                    .Where(n => !string.IsNullOrEmpty(n))
                                    .Distinct()
                                    .Except(callExpr.Args.MaybeEnumerate().Select(a => a.Name).Where(n => !string.IsNullOrEmpty(n)))
                                    .Select(n => CompletionItemSource.CreateCompletionItem($"{n}=", CompletionItemKind.Variable))
                                    .ToArray();

                    items = items.Concat(arguments).ToArray();
                }
            }

            var keywords = GetKeywordItems(context, options, scopeStatement);

            items = items.Concat(keywords);

            return(new CompletionResult(items, applicableSpan));
        }
コード例 #29
0
        internal async Task <Reference[]> FindReferences(ReferencesParams @params, CancellationToken cancellationToken)
        {
            var uri = @params.textDocument.uri;

            ProjectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"References in {uri} at {@params.position}");

            var analysis = entry != null ? await entry.GetAnalysisAsync(50, cancellationToken) : null;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(Array.Empty <Reference>());
            }

            tree = GetParseTree(entry, uri, cancellationToken, out var version);
            var extras = new List <Reference>();

            if (@params.context?.includeDeclaration ?? false)
            {
                var index = tree.LocationToIndex(@params.position);
                var w     = new ImportedModuleNameWalker(entry, index, tree);
                tree.Walk(w);

                if (w.ImportedType != null)
                {
                    @params._expr = w.ImportedType.Name;
                }
                else
                {
                    foreach (var n in w.ImportedModules)
                    {
                        if (Analyzer.Modules.TryGetImportedModule(n.Name, out var modRef) && modRef.AnalysisModule != null)
                        {
                            // Return a module reference
                            extras.AddRange(modRef.AnalysisModule.Locations
                                            .Select(l => new Reference {
                                uri      = l.DocumentUri,
                                range    = l.Span,
                                _version = version?.Version,
                                _kind    = ReferenceKind.Definition
                            })
                                            .ToArray());
                        }
                    }
                }
            }

            IEnumerable <IAnalysisVariable> result;

            if (!string.IsNullOrEmpty(@params._expr))
            {
                TraceMessage($"Getting references for {@params._expr}");
                result = analysis.GetVariables(@params._expr, @params.position);
            }
            else
            {
                var finder = new ExpressionFinder(tree, GetExpressionOptions.FindDefinition);
                if (finder.GetExpression(@params.position) is Expression expr)
                {
                    TraceMessage($"Getting references for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");
                    result = analysis.GetVariables(expr, @params.position);
                }
                else
                {
                    TraceMessage($"No references found in {uri} at {@params.position}");
                    result = Enumerable.Empty <IAnalysisVariable>();
                }
            }

            var filtered = result.Where(v => v.Type != VariableType.None);

            if (!(@params.context?.includeDeclaration ?? false))
            {
                filtered = filtered.Where(v => v.Type != VariableType.Definition);
            }
            if (!(@params.context?._includeValues ?? false))
            {
                filtered = filtered.Where(v => v.Type != VariableType.Value);
            }

            var res = filtered.Select(v => new Reference {
                uri      = v.Location.DocumentUri,
                range    = v.Location.Span,
                _kind    = ToReferenceKind(v.Type),
                _version = version?.Version
            })
                      .Concat(extras)
                      .GroupBy(r => r, ReferenceComparer.Instance)
                      .Select(g => g.OrderByDescending(r => (SourceLocation)r.range.end).ThenBy(r => (int?)r._kind ?? int.MaxValue).First())
                      .ToArray();

            return(res);
        }
コード例 #30
0
        public ExpressionResult FindExpression(string text, int offset)
        {
            Init(text, offset);

            ExpressionFinder p = new ExpressionFinder();

            lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(text));
            Token t = lexer.NextToken();

            // put all tokens in front of targetPosition into the EF-Parser
            while (t.EndLocation < targetPosition)
            {
                p.InformToken(t);
                t = lexer.NextToken();
            }

            // put current token into EF-Parser if it cannot be continued (is simple operator)
            if (t.EndLocation == targetPosition && ((t.Kind <= Tokens.ColonAssign && t.Kind > Tokens.Identifier) || t.Kind == Tokens.EOL))
            {
                p.InformToken(t);
                t = lexer.NextToken();
            }

            // make sure semantic actions are executed
            p.Advance();

            // remember current state, we'll use it to determine the context
            var block = p.CurrentBlock;

            ExpressionContext context = p.IsIdentifierExpected && !p.IsMissingModifier ? ExpressionContext.IdentifierExpected : GetContext(block);

            BitArray expectedSet;

            try {
                expectedSet = p.GetExpectedSet();
            } catch (InvalidOperationException) {
                expectedSet = null;
            }

            // put current token into EF-Parser
            if (t.Location < targetPosition)
            {
                p.InformToken(t);
            }

            if (p.Errors.Any())
            {
                foreach (var e in p.Errors)
                {
                    LoggingService.Warn("not expected: " + e);
                }
            }

            if (p.NextTokenIsPotentialStartOfExpression)
            {
                return(new ExpressionResult("", new DomRegion(targetPosition.Line, targetPosition.Column), context, expectedSet));
            }

            int lastExpressionStartOffset = LocationToOffset(p.CurrentBlock.lastExpressionStart);

            if (lastExpressionStartOffset < 0)
            {
                return(new ExpressionResult("", new DomRegion(targetPosition.Line, targetPosition.Column), context, expectedSet));
            }

            return(MakeResult(text, lastExpressionStartOffset, offset, context, expectedSet));
        }
コード例 #31
0
        static int SmartIndentInternal(ITextEditor editor, int begin, int end)
        {
            ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.VBNet, new StringReader(editor.Document.Text));

            ExpressionFinder context = new ExpressionFinder();

            Stack <string> indentation = new Stack <string>();

            indentation.Push(string.Empty);

            List <int> eols = new List <int>();

            bool inInterface    = false;
            bool isMustOverride = false;
            bool isDeclare      = false;
            bool isDelegate     = false;

            Token currentToken = null;
            Token prevToken    = null;

            int blockStart    = 1;
            int lambdaNesting = 0;

            bool sawAttribute = false;

            while ((currentToken = lexer.NextToken()).Kind != Tokens.EOF)
            {
                if (context.InContext(Context.Attribute) && currentToken.Kind == Tokens.GreaterThan)
                {
                    sawAttribute = true;
                }

                context.InformToken(currentToken);

                if (prevToken == null)
                {
                    prevToken = currentToken;
                }

                if (currentToken.Kind == Tokens.MustOverride)
                {
                    isMustOverride = true;
                }

                if (currentToken.Kind == Tokens.Delegate)
                {
                    isDelegate = true;
                }

                if (currentToken.Kind == Tokens.Declare)
                {
                    isDeclare = true;
                }

                if (currentToken.Kind == Tokens.EOL)
                {
                    isDelegate = isDeclare = isMustOverride = sawAttribute = false;
                    eols.Add(currentToken.Location.Line);
                }

                if (IsBlockEnd(currentToken, prevToken))
                {
                    // indent the lines inside the block
                    // this is an End-statement
                    // hence we indent from blockStart to the previous line
                    int blockEnd = currentToken.Location.Line - 1;

                    // if this is a lambda end include End-Statement in block
//					if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub)) {
//						blockEnd++;
//					}

                    ApplyToRange(editor, indentation, eols, blockStart, blockEnd, begin, end, sawAttribute);

                    if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub))
                    {
                        Unindent(indentation);

                        ApplyToRange(editor, indentation, eols, currentToken.Location.Line, currentToken.Location.Line, begin, end, sawAttribute);
                    }

                    if (currentToken.Kind == Tokens.Interface)
                    {
                        inInterface = false;
                    }

                    if (!inInterface && !isMustOverride && !isDeclare && !isDelegate)
                    {
                        Unindent(indentation);

                        if (currentToken.Kind == Tokens.Select)
                        {
                            Unindent(indentation);
                        }
                    }

                    // block start is this line (for the lines between two blocks)
                    blockStart = currentToken.Location.Line;

                    if (lambdaNesting > 0 && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub))
                    {
                        blockStart++;
                        lambdaNesting--;
                    }
                }

                bool isMultiLineLambda;
                if (IsBlockStart(lexer, currentToken, prevToken, out isMultiLineLambda))
                {
                    // indent the lines between the last and this block
                    // this is a Begin-statement
                    // hence we indent from blockStart to the this line
                    int lastVisualLine = FindNextEol(lexer);
                    eols.Add(lastVisualLine);
                    ApplyToRange(editor, indentation, eols, blockStart, lastVisualLine, begin, end, sawAttribute);

                    if (isMultiLineLambda && (currentToken.Kind == Tokens.Function || currentToken.Kind == Tokens.Sub))
                    {
                        lambdaNesting++;
                        int endColumn   = currentToken.Location.Column;
                        int startColumn = DocumentUtilitites.GetWhitespaceAfter(editor.Document, editor.Document.GetLine(lastVisualLine).Offset).Length;
                        if (startColumn < endColumn)
                        {
                            Indent(editor, indentation, new string(' ', endColumn - startColumn - 1));
                        }
                    }

                    if (!inInterface && !isMustOverride && !isDeclare && !isDelegate)
                    {
                        Indent(editor, indentation);

                        if (currentToken.Kind == Tokens.Select)
                        {
                            Indent(editor, indentation);
                        }
                    }

                    if (currentToken.Kind == Tokens.Interface)
                    {
                        inInterface = true;
                    }

                    // block start is the following line (for the lines inside a block)
                    blockStart = lastVisualLine + 1;
                }

                prevToken = currentToken;
            }

            ApplyToRange(editor, indentation, eols, blockStart, editor.Document.TotalNumberOfLines, begin, end, sawAttribute);

            return((indentation.PeekOrDefault() ?? string.Empty).Length);
        }
コード例 #32
0
ファイル: Server.Hover.cs プロジェクト: willv84/PTVS
        internal Task <Hover> Hover(TextDocumentPositionParams @params, CancellationToken cancellationToken)
        {
            var uri = @params.textDocument.uri;

            ProjectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"Hover in {uri} at {@params.position}");

            var analysis = entry?.Analysis;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(Task.FromResult(EmptyHover));
            }

            tree = GetParseTree(entry, uri, cancellationToken, out var version) ?? tree;

            Expression expr;
            SourceSpan?exprSpan;

            Analyzer.InterpreterScope scope = null;

            var finder = new ExpressionFinder(tree, GetExpressionOptions.Hover);

            expr     = finder.GetExpression(@params.position) as Expression;
            exprSpan = expr?.GetSpan(tree);

            if (expr == null)
            {
                TraceMessage($"No hover info found in {uri} at {@params.position}");
                return(Task.FromResult(EmptyHover));
            }

            TraceMessage($"Getting hover for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");

            // First try values from expression. This works for the import statement most of the time.
            var values = analysis.GetValues(expr, @params.position, scope).ToList();

            if (values.Count == 0)
            {
                // See if this is hover over import statement
                var index = tree.LocationToIndex(@params.position);
                var w     = new ImportedModuleNameWalker(entry, index, tree);
                tree.Walk(w);

                if (w.ImportedType != null)
                {
                    values = analysis.GetValues(w.ImportedType.Name, @params.position).ToList();
                }
                else
                {
                    var sb   = new StringBuilder();
                    var span = SourceSpan.Invalid;
                    foreach (var n in w.ImportedModules)
                    {
                        if (Analyzer.Modules.TryGetImportedModule(n.Name, out var modRef) && modRef.AnalysisModule != null)
                        {
                            if (sb.Length > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine();
                            }
                            sb.Append(_displayTextBuilder.GetModuleDocumentation(modRef));
                            span = span.IsValid ? span.Union(n.SourceSpan) : n.SourceSpan;
                        }
                    }
                    if (sb.Length > 0)
                    {
                        return(Task.FromResult(new Hover {
                            contents = sb.ToString(),
                            range = span
                        }));
                    }
                }
            }

            if (values.Count > 0)
            {
                string originalExpr;
                if (expr is ConstantExpression || expr is ErrorExpression)
                {
                    originalExpr = null;
                }
                else
                {
                    originalExpr = @params._expr?.Trim();
                    if (string.IsNullOrEmpty(originalExpr))
                    {
                        originalExpr = expr.ToCodeString(tree, CodeFormattingOptions.Traditional);
                    }
                }

                var names = values.Select(GetFullTypeName).Where(n => !string.IsNullOrEmpty(n)).Distinct().ToArray();
                var res   = new Hover {
                    contents = GetMarkupContent(
                        _displayTextBuilder.GetDocumentation(values, originalExpr),
                        _clientCaps.textDocument?.hover?.contentFormat),
                    range      = exprSpan,
                    _version   = version?.Version,
                    _typeNames = names
                };
                return(Task.FromResult(res));
            }

            return(Task.FromResult(EmptyHover));
        }