Beispiel #1
0
        private void OnWorkspaceFileDeleted(object sender, FileSystemEventArgs e)
        {
            var entry = _analyzer?.GetAnalysisEntryFromPath(e.FullPath);

            if (entry != null)
            {
                lock (_pendingChanges) {
                    _pendingDeletes.Add(entry);
                    try {
                        _deferredWorkspaceFileChangeNotification.Change(500, Timeout.Infinite);
                    } catch (ObjectDisposedException) {
                    }
                }
            }
        }
Beispiel #2
0
        /// <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 teh 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>
        /// <param name="view"></param>
        /// <param name="buffer"></param>
        /// <param name="provider"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        internal static bool TryGetAnalysisEntry(this ITextView view, ITextBuffer buffer, IServiceProvider provider, out AnalysisEntry entry)
        {
            IPythonInteractiveIntellisense evaluator;

            if ((evaluator = buffer.GetInteractiveWindow()?.Evaluator as IPythonInteractiveIntellisense) != null)
            {
                var analyzer = evaluator.Analyzer;
                if (analyzer != null && !string.IsNullOrEmpty(evaluator.AnalysisFilename))
                {
                    entry = analyzer.GetAnalysisEntryFromPath(evaluator.AnalysisFilename);
                }
                else
                {
                    entry = null;
                }
                return(entry != null);
            }

            string path = buffer.GetFilePath();

            if (path != null)
            {
                var docTable = (IVsRunningDocumentTable4)provider.GetService(typeof(SVsRunningDocumentTable));
                var cookie   = VSConstants.VSCOOKIE_NIL;
                try {
                    cookie = docTable.GetDocumentCookie(path);
                } catch (ArgumentException) {
                    // Exception may be raised while VS is shutting down
                    entry = null;
                    return(false);
                }
                VsProjectAnalyzer analyzer = null;
                if (cookie != VSConstants.VSCOOKIE_NIL)
                {
                    IVsHierarchy hierarchy;
                    uint         itemid;
                    docTable.GetDocumentHierarchyItem(cookie, out hierarchy, out itemid);
                    if (hierarchy != null)
                    {
                        var pyProject = hierarchy.GetProject()?.GetPythonProject();
                        if (pyProject != null)
                        {
                            analyzer = pyProject.GetAnalyzer();
                        }
                    }
                }

                if (analyzer == null && view != null)
                {
                    // We could spin up a new analyzer for non Python projects...
                    analyzer = view.GetBestAnalyzer(provider);
                }

                entry = analyzer?.GetAnalysisEntryFromPath(path);
                return(entry != null);
            }

            entry = null;
            return(false);
        }
Beispiel #3
0
        /// <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 teh 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>
        /// <param name="view"></param>
        /// <param name="buffer"></param>
        /// <param name="provider"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        internal static bool TryGetAnalysisEntry(this ITextView view, ITextBuffer buffer, IServiceProvider provider, out AnalysisEntry entry)
        {
            PythonReplEvaluator   evaluator;
            IInteractiveEvaluator interactiveEval;

            if ((buffer.Properties.TryGetProperty(typeof(IInteractiveEvaluator), out interactiveEval) &&
                 (evaluator = interactiveEval as PythonReplEvaluator) != null) ||
                (view != null && view.Properties.TryGetProperty(typeof(PythonReplEvaluator), out evaluator)))
            {
                var analyzer = evaluator.ReplAnalyzer;
                entry = analyzer.GetAnalysisEntryFromPath(evaluator.AnalysisFilename);
                return(entry != null);
            }

            string path = buffer.GetFilePath();

            if (path != null)
            {
                var docTable = provider.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable4;
                var cookie   = docTable.GetDocumentCookie(path);
                VsProjectAnalyzer analyzer = null;
                if (cookie != VSConstants.VSCOOKIE_NIL)
                {
                    IVsHierarchy hierarchy;
                    uint         itemid;
                    docTable.GetDocumentHierarchyItem(cookie, out hierarchy, out itemid);
                    if (hierarchy != null)
                    {
                        var pyProject = hierarchy.GetProject()?.GetPythonProject();
                        if (pyProject != null)
                        {
                            analyzer = pyProject.GetAnalyzer();
                        }
                    }
                }

                if (analyzer == null && view != null)
                {
                    // We could spin up a new analyzer for non Python projects...
                    analyzer = view.GetBestAnalyzer(provider);
                }

                entry = analyzer?.GetAnalysisEntryFromPath(path);
                return(entry != null);
            }

            entry = null;
            return(false);
        }
Beispiel #4
0
            public SimpleLocationInfo(VsProjectAnalyzer analyzer, IServiceProvider serviceProvider, string searchText, LocationInfo locInfo, StandardGlyphGroup glyphType)
            {
                _serviceProvider = serviceProvider;
                _locationInfo    = locInfo;
                _glyphType       = glyphType;
                _pathText        = GetSearchDisplayText();
                AnalysisEntry entry = analyzer.GetAnalysisEntryFromPath(_locationInfo.FilePath);

                if (entry != null)
                {
                    _lineText = entry.GetLine(_locationInfo.StartLine) ?? "";
                }
                else
                {
                    _lineText = "";
                }
            }
Beispiel #5
0
        public LocationPreviewItem(VsProjectAnalyzer analyzer, FilePreviewItem parent, AnalysisLocation locationInfo, VariableType type)
        {
            _lineNo   = locationInfo.Line;
            _columnNo = locationInfo.Column;
            _parent   = parent;
            var analysis = analyzer.GetAnalysisEntryFromPath(locationInfo.FilePath);

            _type = type;
            if (analysis != null)
            {
                string text    = analysis.GetLine(locationInfo.Line) ?? "";
                string trimmed = text.TrimStart(_whitespace);
                _text = trimmed;
                _span = new Span(_columnNo - (text.Length - trimmed.Length) - 1, parent.Engine.OriginalName.Length);
                if (String.Compare(_text, _span.Start, parent.Engine.OriginalName, 0, parent.Engine.OriginalName.Length) != 0)
                {
                    // we are renaming a name mangled name (or we have a bug where the names aren't lining up).
                    Debug.Assert(_text.Substring(_span.Start, _span.Length + 1 + parent.Engine.PrivatePrefix.Length) == "_" + parent.Engine.PrivatePrefix + parent.Engine.OriginalName);


                    if (parent.Engine.Request.Name.StartsWith("__"))
                    {
                        // if we're renaming to a private prefix name then we just rename the non-prefixed portion
                        _span      = new Span(_span.Start + 1 + parent.Engine.PrivatePrefix.Length, _span.Length);
                        _columnNo += 1 + parent.Engine.PrivatePrefix.Length;
                    }
                    else
                    {
                        // otherwise we renmae the prefixed and non-prefixed portion
                        _span = new Span(_span.Start, _span.Length + 1 + parent.Engine.PrivatePrefix.Length);
                    }
                }
            }
            else
            {
                _text = String.Empty;
            }
        }
Beispiel #6
0
        public static LocationPreviewItem Create(VsProjectAnalyzer analyzer, FilePreviewItem parent, LocationInfo locationInfo, VariableType type)
        {
            Debug.Assert(locationInfo.StartColumn >= 1, "Invalid location info (Column)");
            Debug.Assert(locationInfo.StartLine >= 1, "Invalid location info (Line)");

            var origName = parent?.Engine?.OriginalName;

            if (string.IsNullOrEmpty(origName))
            {
                return(null);
            }

            var analysis = analyzer.GetAnalysisEntryFromUri(locationInfo.DocumentUri) ??
                           analyzer.GetAnalysisEntryFromPath(locationInfo.FilePath);

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

            var text = analysis.GetLine(locationInfo.StartLine);

            if (string.IsNullOrEmpty(text))
            {
                return(null);
            }

            int start, length;

            if (!GetSpan(text, origName, locationInfo, out start, out length))
            {
                // Name does not match exactly, so we might be renaming a prefixed name
                var prefix = parent.Engine.PrivatePrefix;
                if (string.IsNullOrEmpty(prefix))
                {
                    // No prefix available, so don't rename this
                    return(null);
                }

                var newName = parent.Engine.Request.Name;
                if (string.IsNullOrEmpty(newName))
                {
                    // No incoming name
                    Debug.Fail("No incoming name");
                    return(null);
                }

                if (!GetSpanWithPrefix(text, origName, locationInfo, prefix, newName, out start, out length))
                {
                    // Not renaming a prefixed name
                    return(null);
                }
            }

            if (start < 0 || length <= 0)
            {
                Debug.Fail("Expected valid span");
                return(null);
            }

            var trimText = text.TrimStart(_whitespace);

            return(new LocationPreviewItem(
                       parent,
                       trimText,
                       locationInfo.StartLine,
                       start + 1,
                       new Span(start - (text.Length - trimText.Length), length)
                       ));
        }
Beispiel #7
0
        public LocationPreviewItem(VsProjectAnalyzer analyzer, FilePreviewItem parent, LocationInfo locationInfo, VariableType type)
        {
            Debug.Assert(locationInfo.StartColumn >= 1, "Invalid location info (Column)");
            Debug.Assert(locationInfo.StartLine >= 1, "Invalid location info (Line)");
            _parent = parent;
            Type    = type;
            _text   = string.Empty;

            var origName = _parent?.Engine?.OriginalName;

            if (string.IsNullOrEmpty(origName))
            {
                return;
            }

            var analysis = analyzer.GetAnalysisEntryFromUri(locationInfo.DocumentUri) ??
                           analyzer.GetAnalysisEntryFromPath(locationInfo.FilePath);

            if (analysis == null)
            {
                return;
            }

            var text = analysis.GetLine(locationInfo.StartLine);

            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            int start, length;

            if (!GetSpan(text, origName, locationInfo, out start, out length))
            {
                // Name does not match exactly, so we should be renaming a prefixed name
                var prefix = parent.Engine.PrivatePrefix;
                if (string.IsNullOrEmpty(prefix))
                {
                    // No prefix available, so fail
                    Debug.Fail("Failed to find '{0}' in '{1}' because we had no private prefix".FormatInvariant(origName, text));
                    return;
                }

                var newName = parent.Engine.Request.Name;
                if (string.IsNullOrEmpty(newName))
                {
                    // No incoming name
                    Debug.Fail("No incoming name");
                    return;
                }

                if (!GetSpanWithPrefix(text, origName, locationInfo, "_" + prefix, newName, out start, out length))
                {
                    // Not renaming a prefixed name
                    Debug.Fail("Failed to find '{0}' in '{1}'".FormatInvariant(origName, text));
                    return;
                }
            }

            if (start < 0 || length <= 0)
            {
                Debug.Fail("Expected valid span");
                return;
            }

            _text  = text.TrimStart(_whitespace);
            Line   = locationInfo.StartLine;
            Column = start + 1;
            _span  = new Span(start - (text.Length - _text.Length), length);
        }
Beispiel #8
0
        public PythonEditor(
            string content = null,
            PythonLanguageVersion version = PythonLanguageVersion.V27,
            MockVs vs = null,
            IPythonInterpreterFactory factory = null,
            VsProjectAnalyzer analyzer        = null,
            string filename     = null,
            bool?inProcAnalyzer = null
            )
        {
            if (vs == null)
            {
                _disposeVS = true;
                vs         = new MockVs();
            }
            MockVsTextView view = null;

            try {
                AdvancedEditorOptions advancedOptions = null;
                vs.InvokeSync(() => {
                    advancedOptions = vs.GetPyService().AdvancedOptions;
                    advancedOptions.AutoListMembers     = true;
                    advancedOptions.AutoListIdentifiers = false;
                });
                AdvancedOptions = advancedOptions;

                if (factory == null)
                {
                    vs.InvokeSync(() => {
                        factory = vs.ComponentModel.GetService <IInterpreterRegistryService>()
                                  .Interpreters
                                  .FirstOrDefault(c => c.GetLanguageVersion() == version && c.Configuration.Id.StartsWith("Global|PythonCore"));
                        if (factory != null)
                        {
                            Console.WriteLine($"Using interpreter {factory.Configuration.InterpreterPath}");
                        }
                    });
                    if (factory == null)
                    {
                        _disposeFactory = true;
                        factory         = InterpreterFactoryCreator.CreateAnalysisInterpreterFactory(version.ToVersion());
                        Console.WriteLine("Using analysis-only interpreter");
                    }
                }
                if (analyzer == null)
                {
                    _disposeAnalyzer = true;
                    analyzer         = vs.InvokeTask(() => VsProjectAnalyzer.CreateForTestsAsync(vs.ComponentModel.GetService <PythonEditorServices>(), factory, inProcAnalyzer ?? Debugger.IsAttached));
                }
                if (string.IsNullOrEmpty(filename))
                {
                    do
                    {
                        filename = PathUtils.GetAbsoluteFilePath(TestData.GetTempPath(), Path.GetRandomFileName()) + ".py";
                    } while (File.Exists(filename));
                }

                var cancel = CancellationTokens.After60s;
                using (var mre = new ManualResetEventSlim()) {
                    view = vs.CreateTextView(PythonCoreConstants.ContentType, content ?? "",
                                             v => {
                        v.TextView.TextBuffer.Properties[BufferParser.ParseImmediately]             = true;
                        v.TextView.TextBuffer.Properties[IntellisenseController.SuppressErrorLists] = IntellisenseController.SuppressErrorLists;
                        v.TextView.TextBuffer.Properties[VsProjectAnalyzer._testAnalyzer]           = analyzer;
                        v.TextView.TextBuffer.Properties[VsProjectAnalyzer._testFilename]           = filename;
                    },
                                             filename);

                    var entry = analyzer.GetAnalysisEntryFromPath(filename);
                    while (entry == null && !cancel.IsCancellationRequested)
                    {
                        Thread.Sleep(50);
                        entry = analyzer.GetAnalysisEntryFromPath(filename);
                    }

                    if (!string.IsNullOrEmpty(content) && !cancel.IsCancellationRequested && !entry.IsAnalyzed)
                    {
                        EventHandler evt = (s, e) => mre.SetIfNotDisposed();

                        try {
                            entry.AnalysisComplete += evt;
                            while (!mre.Wait(50, cancel) && !vs.HasPendingException && !entry.IsAnalyzed)
                            {
                                if (!analyzer.IsAnalyzing && !entry.IsAnalyzed)
                                {
                                    var bp = entry.TryGetBufferParser();
                                    Assert.IsNotNull(bp, "No buffer parser was ever created");
                                    var bi = PythonTextBufferInfo.TryGetForBuffer(view.TextView.TextBuffer);
                                    Assert.IsNotNull(bi, "No BufferInfo was ever created");
                                    bi.LastSentSnapshot = null;
                                    bp.EnsureCodeSyncedAsync(view.TextView.TextBuffer).WaitAndUnwrapExceptions();
                                }
                            }
                        } catch (OperationCanceledException) {
                        } finally {
                            entry.AnalysisComplete -= evt;
                        }
                    }
                    if (cancel.IsCancellationRequested)
                    {
                        Assert.Fail("Timed out waiting for code analysis");
                    }

                    vs.ThrowPendingException();
                }

                View     = view;
                view     = null;
                Analyzer = analyzer;
                analyzer = null;
                Factory  = factory;
                factory  = null;
                VS       = vs;
                vs       = null;
            } finally {
                if (view != null)
                {
                    view.Dispose();
                }
                if (analyzer != null && _disposeAnalyzer)
                {
                    analyzer.Dispose();
                }
                if (factory != null && _disposeFactory)
                {
                    var disp = factory as IDisposable;
                    if (disp != null)
                    {
                        disp.Dispose();
                    }
                }
                if (vs != null && _disposeVS)
                {
                    vs.Dispose();
                }
            }
        }