Exemple #1
0
            public ClassifierHelper(string code, PythonLanguageVersion version)
            {
                _view = new PythonEditor("", version);

                var providers = _view.VS.ComponentModel.GetExtensions <IClassifierProvider>().ToArray();

                _provider1 = providers.OfType <PythonClassifierProvider>().Single();
                _provider2 = providers.OfType <PythonAnalysisClassifierProvider>().Single();

                _classificationsReady1 = new ManualResetEventSlim();
                _classificationsReady2 = new ManualResetEventSlim();

                AstClassifier.ClassificationChanged += (s, e) => _classificationsReady1.SetIfNotDisposed();
                var startVersion = _view.CurrentSnapshot.Version;

                AnalysisClassifier.ClassificationChanged += (s, e) => {
                    try {
                        var bi = PythonTextBufferInfo.TryGetForBuffer(_view.View.TextView.TextBuffer);
                        if (bi?.LastAnalysisReceivedVersion == null)
                        {
                            return;
                        }
                        // make sure we have classifications from the version we analyzed after
                        // setting the text below.
                        if (bi.LastAnalysisReceivedVersion.VersionNumber > startVersion.VersionNumber)
                        {
                            _classificationsReady2.SetIfNotDisposed();
                        }
                    } catch (Exception ex) {
                        _excInfo = ExceptionDispatchInfo.Capture(ex);
                    }
                };

                _view.Text = code;
            }
Exemple #2
0
        internal int RemoveBuffer(ITextBuffer subjectBuffer)
        {
            int result;
            var bi = PythonTextBufferInfo.TryGetForBuffer(subjectBuffer);

            lock (this) {
                if (bi != null)
                {
                    var existing = _buffers.FirstOrDefault(b => b.Buffer == bi);
                    if (existing != null && existing.Release())
                    {
                        _buffers = _buffers.Where(b => b != existing).ToArray();

                        bi.RemoveSink(this);

                        VsProjectAnalyzer.DisconnectErrorList(bi);
                        _bufferIdMapping.Remove(bi.AnalysisBufferId);
                        bi.SetAnalysisBufferId(-1);

                        bi.Buffer.Properties.RemoveProperty(typeof(PythonTextBufferInfo));
                    }
                }
                result = _buffers.Length;
            }

            return(result);
        }
Exemple #3
0
        private static void ValidateBufferContents(IEnumerable <ITextSnapshot> snapshots, AP.FileUpdateResponse response)
        {
#if DEBUG
            if (response.newCode == null)
            {
                return;
            }

            foreach (var snapshot in snapshots)
            {
                var bi = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);
                if (bi == null)
                {
                    continue;
                }

                string newCode;
                if (!response.newCode.TryGetValue(bi.AnalysisBufferId, out newCode))
                {
                    continue;
                }

                if (newCode.TrimEnd() != snapshot.GetText().TrimEnd())
                {
                    Console.Error.WriteLine($"New Code: [{newCode}]");
                    Console.Error.WriteLine($"Snapshot: [{snapshot.GetText()}]");
                    Debug.Fail("Buffer content mismatch");
                }
            }
#endif
        }
Exemple #4
0
        public void BasicProjectTest()
        {
            var sln = Generator.Project(
                "HelloWorld",
                ProjectGenerator.Compile("server", "")
                ).Generate();

            using (var vs = sln.ToMockVs()) {
                Assert.IsNotNull(vs.WaitForItem("HelloWorld", "Python Environments"));
                Assert.IsNotNull(vs.WaitForItem("HelloWorld", "References"));
                Assert.IsNotNull(vs.WaitForItem("HelloWorld", "Search Paths"));
                Assert.IsNotNull(vs.WaitForItem("HelloWorld", "server.py"));
                var view = vs.OpenItem("HelloWorld", "server.py");

                var bi = PythonTextBufferInfo.TryGetForBuffer(view.TextView.TextBuffer);
                for (int retries = 20; retries > 0 && bi.AnalysisEntry == null; --retries)
                {
                    Thread.Sleep(500);
                }

                view.Invoke(() => view.Type("import"));
                view.Invoke(() => view.Type(" "));

                using (var sh = view.WaitForSession <ICompletionSession>()) {
                    AssertUtil.Contains(sh.Session.Completions(), "sys");
                }
            }
        }
Exemple #5
0
        private static void ValidateBufferContents(IEnumerable <ITextSnapshot> snapshots, AP.FileUpdateResponse response)
        {
#if DEBUG
            if (response.newCode == null)
            {
                return;
            }

            foreach (var snapshot in snapshots)
            {
                var bi = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);
                if (bi == null)
                {
                    continue;
                }

                string newCode;
                if (!response.newCode.TryGetValue(bi.AnalysisBufferId, out newCode))
                {
                    continue;
                }

                Debug.Assert(newCode.TrimEnd() == snapshot.GetText().TrimEnd(), "Buffer content mismatch");
            }
#endif
        }
Exemple #6
0
        internal PythonTextBufferInfo GetBufferInfo()
        {
            var bi = PythonTextBufferInfo.TryGetForBuffer(TextBuffer);

            Debug.Assert(bi != null, "Getting completions from uninitialized buffer " + TextBuffer.ToString());
            return(bi);
        }
Exemple #7
0
        internal AnalysisEntry GetAnalysisEntry()
        {
            var bi = PythonTextBufferInfo.TryGetForBuffer(TextBuffer);

            Debug.Assert(bi != null, "Getting completions from uninitialized buffer " + TextBuffer.ToString());
            Debug.Assert(bi?.AnalysisEntry != null, "Failed to get project entry for buffer " + TextBuffer.ToString());
            return(bi?.AnalysisEntry);
        }
        internal bool GetPrecedingExpression(out string parentExpression, out SnapshotSpan expressionExtent)
        {
            parentExpression = string.Empty;
            expressionExtent = default(SnapshotSpan);

            var bi = PythonTextBufferInfo.TryGetForBuffer(_snapshot.TextBuffer);

            if (bi == null)
            {
                return(false);
            }
            var span = Span.GetSpan(_snapshot);
            var expr = bi.GetExpressionAtPoint(span, GetExpressionOptions.EvaluateMembers);

            if (expr != null)
            {
                parentExpression = expr.Value.GetText() ?? "";
                expressionExtent = new SnapshotSpan(expr.Value.Start, span.End);
                return(true);
            }

            expr = bi.GetExpressionAtPoint(span, GetExpressionOptions.Rename);
            if (expr != null)
            {
                expressionExtent = expr.Value;
                return(true);
            }

            var tok = bi.GetTokenAtPoint(span.End);

            if (tok == null)
            {
                expressionExtent = span;
                return(true);
            }

            switch (tok.Value.Category)
            {
            case TokenCategory.Delimiter:
            case TokenCategory.Grouping:
            case TokenCategory.Operator:
            case TokenCategory.WhiteSpace:
                // Expect top-level completions after these
                expressionExtent = span;
                return(true);

            case TokenCategory.BuiltinIdentifier:
            case TokenCategory.Identifier:
            case TokenCategory.Keyword:
                // Expect filtered top-level completions here
                // (but the return value is no different)
                expressionExtent = span;
                return(true);
            }

            return(false);
        }
Exemple #9
0
        public static Task <AnalysisEntry> GetAnalysisEntryAsync(this ITextBuffer buffer, PythonEditorServices services = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var bi = services == null?PythonTextBufferInfo.TryGetForBuffer(buffer) : services.GetBufferInfo(buffer);

            if (bi != null)
            {
                return(bi.GetAnalysisEntryAsync(cancellationToken));
            }
            return(Task.FromResult <AnalysisEntry>(null));
        }
        public bool TryGetAnalyzer(ITextBuffer textBuffer, out ProjectAnalyzer analyzer, out string filename)
        {
            // If we have an analyzer in Properties, we will use that
            // NOTE: This should only be used for tests.
            if (textBuffer.Properties.TryGetProperty(VsProjectAnalyzer._testAnalyzer, out analyzer))
            {
                if (!textBuffer.Properties.TryGetProperty(VsProjectAnalyzer._testFilename, out filename))
                {
                    filename = textBuffer.GetFilePath();
                }
                return(true);
            }

            // Fastest check is for an existing analysis entry
            var bufferInfo = PythonTextBufferInfo.TryGetForBuffer(textBuffer);

            if (bufferInfo?.AnalysisEntry != null)
            {
                analyzer = bufferInfo.AnalysisEntry.Analyzer;
                filename = bufferInfo.Filename;
                return(true);
            }

            // If we have a REPL evaluator we'll use its analyzer
            IPythonInteractiveIntellisense evaluator;

            if ((evaluator = textBuffer.GetInteractiveWindow()?.Evaluator as IPythonInteractiveIntellisense) != null)
            {
                analyzer = evaluator.Analyzer;
                filename = evaluator.AnalysisFilename;
                return(true);
            }

            // If we find an associated project, use its analyzer
            // This should only happen while racing with text view creation
            var path = PythonTextBufferInfo.TryGetForBuffer(textBuffer)?.Filename ?? textBuffer.GetFilePath();

            if (path != null)
            {
                analyzer = _services.Site.GetProjectFromFile(path)?.GetAnalyzer();
                if (analyzer != null)
                {
                    // Don't check whether the analyzer knows about us yet,
                    // since this request is probably finding out which analyzer
                    // to add the file to.
                    filename = path;
                    return(true);
                }
            }

            analyzer = null;
            filename = null;
            return(false);
        }
Exemple #11
0
 private void BufferGraph_GraphBuffersChanged(object sender, VisualStudio.Text.Projection.GraphBuffersChangedEventArgs e)
 {
     foreach (var b in e.RemovedBuffers)
     {
         PythonTextBufferInfo.TryGetForBuffer(b)?.RemoveSink(typeof(DropDownBarClient));
     }
     foreach (var b in e.AddedBuffers)
     {
         _services.GetBufferInfo(b).AddSink(typeof(DropDownBarClient), this);
     }
 }
Exemple #12
0
 public int GetBufferId(ITextBuffer buffer)
 {
     // May get null if there is no analysis entry associated with the file yet.
     // This can happen when you have a document that is open but hasn't had focus
     // causing the full load of our intellisense controller.  In that case there
     // is only a single buffer which is buffer 0.  An easy repro for this is to
     // open a IronPython WPF project and close it with the XAML file focused and
     // the .py file still open. Re-open the project, and double click on a button
     // on the XAML page.  The python file isn't loaded and we have no
     // PythonTextBufferInfo associated with it.
     return(PythonTextBufferInfo.TryGetForBuffer(buffer)?.AnalysisBufferId ?? 0);
 }
        /// <summary>
        /// Gets the internal analyzer object from either a text view or buffer. Both arguments
        /// are optional, and <c>null</c> may be passed.
        /// </summary>
        public VsProjectAnalyzer GetVsAnalyzer(ITextView view, ITextBuffer buffer)
        {
            // This function has to do everything it can to find an analyzer
            // without an AnalysisEntry, so that callers can use this to find
            // the right analyzer to create the entry for.

            buffer = buffer ?? view?.TextBuffer;
            if (buffer == null)
            {
                return(null);
            }

            // Quick check for an existing entry
            var bufferInfo = PythonTextBufferInfo.TryGetForBuffer(buffer);

            if (bufferInfo?.AnalysisEntry?.Analyzer != null)
            {
                return(bufferInfo.AnalysisEntry.Analyzer);
            }

            // If we have an analyzer in Properties, we will use that
            // NOTE: This should only be used for tests.
            ProjectAnalyzer analyzer;

            if (buffer.Properties.TryGetProperty(VsProjectAnalyzer._testAnalyzer, out analyzer))
            {
                return(analyzer as VsProjectAnalyzer);
            }

            // If we have a REPL evaluator we'll use its analyzer
            IPythonInteractiveIntellisense evaluator;

            if ((evaluator = buffer.GetInteractiveWindow()?.Evaluator as IPythonInteractiveIntellisense) != null)
            {
                return(evaluator.Analyzer);
            }

            // If we find an associated project, use its analyzer
            // This should only happen while racing with text view creation
            var path = buffer.GetFilePath();

            if (path != null)
            {
                analyzer = _services.Site.GetProjectFromFile(path)?.GetAnalyzer();
                if (analyzer is VsProjectAnalyzer vpa)
                {
                    return(vpa);
                }
            }

            return(null);
        }
Exemple #14
0
        public static PythonClassifier GetPythonClassifier(this ITextBuffer buffer)
        {
            var bi = PythonTextBufferInfo.TryGetForBuffer(buffer);

            if (bi == null)
            {
                return(null);
            }

            var provider = bi.Services.ComponentModel.GetService <PythonClassifierProvider>();

            return(provider.GetClassifier(buffer) as PythonClassifier);
        }
Exemple #15
0
        internal static async Task ParseBuffersAsync(
            PythonEditorServices services,
            VsProjectAnalyzer analyzer,
            IEnumerable <ITextSnapshot> snapshots
            )
        {
            var updates = snapshots
                          .GroupBy(s => PythonTextBufferInfo.TryGetForBuffer(s.TextBuffer)?.AnalysisEntry.FileId ?? -1)
                          .Where(g => g.Key >= 0)
                          .Select(g => Tuple.Create(
                                      g.Key,
                                      g.Select(s => GetUpdateForSnapshot(services, s)).Where(u => u != null).ToArray()
                                      ))
                          .ToList();

            if (!updates.Any())
            {
                return;
            }


            foreach (var update in updates)
            {
                if (update.Item1 < 0)
                {
                    continue;
                }

                analyzer._analysisComplete = false;
                Interlocked.Increment(ref analyzer._parsePending);

                var res = await analyzer.SendRequestAsync(
                    new AP.FileUpdateRequest()
                {
                    fileId  = update.Item1,
                    updates = update.Item2
                }
                    );

                if (res != null)
                {
                    Debug.Assert(res.failed != true);
                    analyzer.OnAnalysisStarted();
                    ValidateBufferContents(snapshots, res);
                }
                else
                {
                    Interlocked.Decrement(ref analyzer._parsePending);
                }
            }
        }
Exemple #16
0
        internal static async Task ParseBuffersAsync(
            PythonEditorServices services,
            VsProjectAnalyzer analyzer,
            IEnumerable <ITextSnapshot> snapshots
            )
        {
            var tasks = new List <Tuple <ITextSnapshot[], Task <AP.FileUpdateResponse> > >();

            foreach (var snapshotGroup in snapshots.GroupBy(s => PythonTextBufferInfo.TryGetForBuffer(s.TextBuffer)))
            {
                var entry = snapshotGroup.Key?.AnalysisEntry;
                if (entry == null)
                {
                    continue;
                }

                var updates = snapshotGroup.Select(s => GetUpdateForSnapshot(snapshotGroup.Key, s)).Where(u => u != null).ToArray();
                if (!updates.Any())
                {
                    continue;
                }

                analyzer._analysisComplete = false;
                Interlocked.Increment(ref analyzer._parsePending);

                tasks.Add(Tuple.Create(snapshotGroup.ToArray(), analyzer.SendRequestAsync(
                                           new AP.FileUpdateRequest {
                    fileId  = entry.FileId,
                    updates = updates
                }
                                           )));
            }

            foreach (var task in tasks)
            {
                var res = await task.Item2;

                if (res != null)
                {
                    Debug.Assert(res.failed != true);
                    analyzer.OnAnalysisStarted();
                    ValidateBufferContents(task.Item1, res);
                }
                else
                {
                    Interlocked.Decrement(ref analyzer._parsePending);
                }
            }
        }
Exemple #17
0
        private Tokenizer GetTokenizer(ITextSnapshot snapshot)
        {
            if (_tokenizers == null)
            {
                _tokenizers = new Dictionary <PythonLanguageVersion, Tokenizer>();
            }
            Tokenizer res;
            var       bi      = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);
            var       version = bi?.LanguageVersion ?? PythonLanguageVersion.None;

            if (!_tokenizers.TryGetValue(version, out res))
            {
                _tokenizers[version] = res = new Tokenizer(version, options: TokenizerOptions.Verbatim | TokenizerOptions.VerbatimCommentsAndLineJoins);
            }
            return(res);
        }
Exemple #18
0
        public int GetDataTipText(TextSpan[] pSpan, out string pbstrText)
        {
            if (!_wpfTextView.TextBuffer.ContentType.IsOfType(PythonCoreConstants.ContentType))
            {
                pbstrText = null;
                return(VSConstants.E_NOTIMPL);
            }

            if (pSpan.Length != 1)
            {
                throw new ArgumentException("Array parameter should contain exactly one TextSpan", "pSpan");
            }

            // Adjust the span to expression boundaries.

            var snapshot = _wpfTextView.TextSnapshot;
            var pt       = new SourceLocation(pSpan[0].iStartLine + 1, pSpan[0].iStartIndex + 1);

            var bi       = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);
            var analyzer = bi?.AnalysisEntry?.Analyzer;

            if (analyzer == null)
            {
                pbstrText = null;
                return(VSConstants.E_FAIL);
            }

            SourceSpan?expr;

            try {
                expr = _editorServices.Site.GetUIThread().InvokeTaskSync(async() => {
                    return(await analyzer.GetExpressionSpanAtPointAsync(bi, pt, ExpressionAtPointPurpose.Hover, TimeSpan.FromSeconds(1.0)));
                }, CancellationTokens.After1s);
            } catch (OperationCanceledException) {
                expr = null;
            }

            if (expr == null)
            {
                pbstrText = null;
                return(VSConstants.E_ABORT);
            }

            var span = expr.Value.ToSnapshotSpan(snapshot);

            return(_debugger.GetDataTipValue(_vsTextLines, pSpan, span.GetText(), out pbstrText));
        }
        public ReverseExpressionParser(ITextSnapshot snapshot, ITextBuffer buffer, ITrackingSpan span)
        {
            _snapshot = snapshot;
            _buffer   = buffer;
            _span     = span;

            var loc  = span.GetSpan(snapshot);
            var line = _curLine = snapshot.GetLineFromPosition(loc.Start);

            var targetSpan = new Span(line.Start.Position, span.GetEndPoint(snapshot).Position - line.Start.Position);

            _classifier = PythonTextBufferInfo.TryGetForBuffer(_buffer)?.Classifier;
            if (_classifier == null)
            {
                throw new ArgumentException(Strings.ReverseExpressionParserFailedToGetClassifierFromBufferException);
            }
        }
        /// <summary>
        /// Gets the analysis entry for the given buffer.
        ///
        /// This will only succeed if the buffer is a file on disk. It is not able to support things like
        /// difference views because we don't know what view this buffer is hosted in. This method should
        /// only be used when we don't know the current view for the buffer. Otherwise, use
        /// <see cref="TryGetAnalysisEntry(ITextView, ITextBuffer, out AnalysisEntry)"/>
        /// </summary>
        public bool TryGetAnalysisEntry(ITextBuffer textBuffer, out AnalysisEntry entry)
        {
            if (textBuffer == null)
            {
                entry = null;
                return(false);
            }

            // If we have a REPL evaluator we'll use its analyzer
            IPythonInteractiveIntellisense evaluator;

            if ((evaluator = textBuffer.GetInteractiveWindow()?.Evaluator as IPythonInteractiveIntellisense) != null)
            {
                entry = evaluator.Analyzer?.GetAnalysisEntryFromPath(evaluator.AnalysisFilename);
                if (entry != null)
                {
                    return(true);
                }
            }

            var bufferInfo = PythonTextBufferInfo.TryGetForBuffer(textBuffer);

            if (bufferInfo?.AnalysisEntry != null)
            {
                entry = bufferInfo.AnalysisEntry;
                return(true);
            }

            // Fall back on finding the analyzer and path separately
            ProjectAnalyzer analyzer;
            string          path;

            if (TryGetAnalyzer(textBuffer, out analyzer, out path))
            {
                entry = (analyzer as VsProjectAnalyzer)?.GetAnalysisEntryFromPath(path);
                if (entry != null)
                {
                    return(true);
                }
            }

            entry = null;
            return(false);
        }
Exemple #21
0
        private static void ValidateBufferContents(IEnumerable <ITextSnapshot> snapshots, Dictionary <int, string> code)
        {
            foreach (var snapshot in snapshots)
            {
                var bi = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);
                if (bi == null)
                {
                    continue;
                }

                string newCode;
                if (!code.TryGetValue(bi.AnalysisEntryId, out newCode))
                {
                    continue;
                }

                Debug.Assert(newCode.TrimEnd() == snapshot.GetText().TrimEnd(), "Buffer content mismatch");
            }
        }
Exemple #22
0
        private void DetachWindow(IInteractiveEvaluator oldEval)
        {
            var oldView = oldEval?.CurrentWindow?.TextView;

            if (oldView != null)
            {
                foreach (var buffer in oldView.BufferGraph.GetTextBuffers(EditorExtensions.IsPythonContent))
                {
                    if (oldEval.CurrentWindow.CurrentLanguageBuffer == buffer)
                    {
                        continue;
                    }

                    var tb = PythonTextBufferInfo.TryGetForBuffer(buffer);
                    if (tb != null)
                    {
                        tb.DoNotParse = true;
                    }
                }
            }
        }
Exemple #23
0
        internal int RemoveBuffer(ITextBuffer subjectBuffer)
        {
            int result;
            var bi = PythonTextBufferInfo.TryGetForBuffer(subjectBuffer);

            lock (this) {
                if (bi != null)
                {
                    EnsureMutableBuffers();
                    _buffers.Remove(bi);
                }
                result = _buffers.Count;
            }

            if (bi != null)
            {
                UninitBuffer(bi);
            }

            return(result);
        }
Exemple #24
0
        protected override async Task <ExecutionResult> ResetWorkerAsync(bool initialize, bool quiet)
        {
            // suppress reporting "failed to launch repl" process
            var thread = Interlocked.Exchange(ref _thread, null);

            if (thread == null)
            {
                if (!quiet)
                {
                    WriteError(Strings.ReplNotStarted);
                }
                return(ExecutionResult.Success);
            }

            foreach (var buffer in CurrentWindow.TextView.BufferGraph.GetTextBuffers(b => b.ContentType.IsOfType(PythonCoreConstants.ContentType)))
            {
                var tb = PythonTextBufferInfo.TryGetForBuffer(buffer);
                if (tb != null)
                {
                    tb.DoNotParse = true;
                }
            }

            if (!quiet)
            {
                WriteOutput(Strings.ReplReset);
            }

            thread.IsProcessExpectedToExit = quiet;
            thread.Dispose();

            var options = _serviceProvider.GetPythonToolsService().InteractiveOptions;

            UseSmartHistoryKeys = options.UseSmartHistory;
            LiveCompletionsOnly = options.LiveCompletionsOnly;

            EnableMultipleScopes = false;

            return(ExecutionResult.Success);
        }
Exemple #25
0
        internal bool GetPrecedingExpression(out string parentExpression, out SnapshotSpan expressionExtent)
        {
            parentExpression = string.Empty;
            expressionExtent = default(SnapshotSpan);

            var bi = PythonTextBufferInfo.TryGetForBuffer(_snapshot.TextBuffer);

            if (bi == null)
            {
                return(false);
            }
            var span = Span.GetSpan(_snapshot);
            var expr = bi.GetExpressionAtPoint(span, GetExpressionOptions.EvaluateMembers);

            if (expr != null)
            {
                parentExpression = expr.Value.GetText() ?? "";
                expressionExtent = new SnapshotSpan(expr.Value.Start, span.End);
                return(true);
            }

            expr = bi.GetExpressionAtPoint(span, GetExpressionOptions.Rename);
            if (expr != null)
            {
                expressionExtent = expr.Value;
                return(true);
            }

            var tok = bi.GetTokenAtPoint(span.End);

            if (tok == null)
            {
                expressionExtent = span;
                return(true);
            }

            return(false);
        }
Exemple #26
0
        //public void SetAnalyzer(ITextBuffer textBuffer, VsProjectAnalyzer analyzer) {
        //    if (textBuffer == null) {
        //        throw new ArgumentNullException(nameof(textBuffer));
        //    }
        //
        //    if (analyzer == null) {
        //        textBuffer.Properties.RemoveProperty(typeof(VsProjectAnalyzer));
        //        return;
        //    }
        //
        //    textBuffer.Properties[typeof(VsProjectAnalyzer)] = analyzer;
        //
        //    TaskCompletionSource<object> tcs;
        //    if (textBuffer.Properties.TryGetProperty(_waitForAnalyzerKey, out tcs)) {
        //        tcs.TrySetResult(null);
        //        textBuffer.Properties.RemoveProperty(_waitForAnalyzerKey);
        //    }
        //}

        /// <summary>
        /// Gets the analysis entry for the given view and buffer.
        ///
        /// For files on disk this is pretty easy - we analyze each file on it's own in a buffer parser.
        /// Therefore we map filename -> analyzer and then get the analysis from the analyzer.  If we
        /// determine an analyzer but the file isn't loaded into it for some reason this would return null.
        /// We can also apply some policy to buffers depending upon the view that they're hosted in.  For
        /// example if a buffer is outside of any projects, but hosted in a difference view with a buffer
        /// that is in a project, then we'll look in the view that has the project.
        ///
        /// For interactive windows we will use the analyzer that's configured for the window.
        /// </summary>
        public bool TryGetAnalysisEntry(ITextView textView, ITextBuffer textBuffer, out AnalysisEntry entry)
        {
            var bi = PythonTextBufferInfo.TryGetForBuffer(textBuffer ?? textView?.TextBuffer);

            if (bi == null && textView != null)
            {
                // If we have a difference viewer we'll match the LHS w/ the RHS
                var viewer = _diffService?.TryGetViewerForTextView(textView);
                if (viewer != null)
                {
                    if (TryGetAnalysisEntry(viewer.DifferenceBuffer.RightBuffer, out entry))
                    {
                        return(true);
                    }
                    if (TryGetAnalysisEntry(viewer.DifferenceBuffer.LeftBuffer, out entry))
                    {
                        return(true);
                    }
                }
            }

            entry = bi?.AnalysisEntry;
            return(entry != null);
        }
Exemple #27
0
        public async Task RenameVariable(IRenameVariableInput input, IVsPreviewChangesService previewChanges)
        {
            if (IsModuleName(input))
            {
                input.CannotRename(Strings.RenameVariable_CannotRenameModuleName);
                return;
            }

            var caret  = _view.GetPythonCaret();
            var entry  = _view.GetAnalysisAtCaret(_serviceProvider);
            var buffer = entry?.TryGetBufferParser()?.DefaultBufferInfo ?? PythonTextBufferInfo.TryGetForBuffer(_view.TextBuffer);

            if (caret == null || entry == null || buffer == null)
            {
                input.CannotRename(Strings.RenameVariable_UnableGetAnalysisCurrentTextView);
                return;
            }
            var analysis = await entry.Analyzer.AnalyzeExpressionAsync(entry, caret.Value, ExpressionAtPointPurpose.Rename);

            if (analysis == null || string.IsNullOrEmpty(analysis.Expression) || !(analysis.Variables?.Any() ?? false))
            {
                input.CannotRename(Strings.RenameVariable_UnableGetExpressionAnalysis);
                return;
            }

            string privatePrefix = analysis.PrivatePrefix;
            var    originalName  = analysis.Variables
                                   .Where(r => r.Type == VariableType.Definition)
                                   .Where(r => r.Location.DocumentUri == buffer.DocumentUri && buffer.LocationTracker.CanTranslateFrom(r.Version ?? -1))
                                   .Select(r => {
                var snapshot = buffer.CurrentSnapshot;
                try {
                    return(buffer.LocationTracker.Translate(r.Location.Span, r.Version ?? -1, snapshot).GetText());
                } catch (ArgumentException) {
                    return(null);
                }
            })
                                   .Where(n => !string.IsNullOrEmpty(n))
                                   .FirstOrDefault() ?? analysis.Expression;

            if (analysis.PrivatePrefix != null && originalName != null && originalName.StartsWithOrdinal("_" + analysis.PrivatePrefix))
            {
                originalName  = originalName.Substring(analysis.PrivatePrefix.Length + 1);
                privatePrefix = analysis.PrivatePrefix;
            }

            if (originalName != null && _view.Selection.IsActive && !_view.Selection.IsEmpty)
            {
                if (_view.Selection.Start.Position < analysis.Span.GetStartPoint(_view.TextBuffer.CurrentSnapshot) ||
                    _view.Selection.End.Position > analysis.Span.GetEndPoint(_view.TextBuffer.CurrentSnapshot))
                {
                    originalName = null;
                }
            }

            if (originalName == null)
            {
                input.CannotRename(Strings.RenameVariable_SelectSymbol);
                return;
            }

            if (!analysis.Variables.Any(v => v.Type == VariableType.Definition || v.Type == VariableType.Reference))
            {
                input.CannotRename(Strings.RenameVariable_NoInformationAvailableForVariable.FormatUI(originalName));
                return;
            }

            PythonLanguageVersion languageVersion = PythonLanguageVersion.None;
            var analyzer = _view.GetAnalyzerAtCaret(_serviceProvider);
            var factory  = analyzer != null ? analyzer.InterpreterFactory : null;

            if (factory != null)
            {
                languageVersion = factory.Configuration.Version.ToLanguageVersion();
            }

            var info = input.GetRenameInfo(originalName, languageVersion);

            if (info != null)
            {
                var engine = new PreviewChangesEngine(_serviceProvider, input, analysis.Expression, info, originalName, privatePrefix, _view.GetAnalyzerAtCaret(_serviceProvider), analysis.Variables);
                if (info.Preview)
                {
                    previewChanges.PreviewChanges(engine);
                }
                else
                {
                    ErrorHandler.ThrowOnFailure(engine.ApplyChanges());
                }
            }
        }
Exemple #28
0
 public static PythonClassifier GetPythonClassifier(this ITextBuffer buffer)
 {
     return(PythonTextBufferInfo.TryGetForBuffer(buffer)?.Classifier);
 }
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            var classifications = new List <ClassificationSpan>();
            var snapshot        = span.Snapshot;

            if (span.Length <= 0 || snapshot.IsReplBufferWithCommand())
            {
                return(classifications);
            }

            var bi = PythonTextBufferInfo.TryGetForBuffer(snapshot.TextBuffer);

            if (bi == null)
            {
                return(classifications);
            }

            AP.AnalysisClassification[] spans;
            int fromVersion;

            lock (_spanCacheLock) {
                spans       = _spanCache;
                fromVersion = _spanFromVersion;
            }

            if (spans == null)
            {
                if (_provider._colorNames)
                {
                    if (bi?.AnalysisEntry != null && bi.AnalysisEntry.IsAnalyzed)
                    {
                        // Trigger the request so we get info on first open
                        OnNewAnalysisAsync(bi, bi.AnalysisEntry).HandleAllExceptions(bi.Services.Site, GetType()).DoNotWait();
                    }
                }

                return(classifications);
            }
            if (spans.Length == 0)
            {
                return(classifications);
            }

            // find where in the spans we should start scanning from (they're sorted by
            // starting position in the old buffer)
            var start      = bi.LocationTracker.Translate(span.Start.ToSourceLocation(), snapshot, fromVersion);
            var end        = bi.LocationTracker.Translate(span.End.ToSourceLocation(), snapshot, fromVersion);
            var startIndex = Array.BinarySearch(spans, start, IndexComparer.Instance);

            if (startIndex < 0)
            {
                startIndex = ~startIndex - 1;
                if (startIndex < 0)
                {
                    startIndex = 0;
                }
            }

            for (int i = startIndex; i < spans.Length; i++)
            {
                var spanSpan = new SourceSpan(
                    new SourceLocation(spans[i].startLine, spans[i].startColumn),
                    new SourceLocation(spans[i].endLine, spans[i].endColumn)
                    );
                if (spanSpan.Start > end)
                {
                    // we're past the span our caller is interested in, stop scanning...
                    break;
                }

                var cs = bi.LocationTracker.Translate(spanSpan, fromVersion, snapshot);

                string typeName = ToVsClassificationName(spans[i]);

                IClassificationType classificationType;
                if (typeName != null &&
                    _provider.CategoryMap.TryGetValue(typeName, out classificationType))
                {
                    classifications.Add(new ClassificationSpan(cs, classificationType));
                }
            }

            return(classifications);
        }
Exemple #30
0
 public static OutliningTaggerProvider.OutliningTagger GetOutliningTagger(this ITextView self)
 {
     return(PythonTextBufferInfo.TryGetForBuffer(self.TextBuffer)?.OutliningTagger);
 }