/// <summary>
        /// Locates and opens existing scope for a node or creates a new scope
        /// as a child of the specified scope. Scope is pushed on the stack
        /// and will be removed when returned the disposable is disposed.
        /// </summary>
        public IDisposable OpenScope(IPythonModule module, ScopeStatement node, out Scope outerScope)
        {
            outerScope = null;
            if (node == null)
            {
                return(Disposable.Empty);
            }

            // During analysis module global scope has not changed yet since it updates
            // When the analysis completed. Therefore if module is the one we are
            // analyzing, use scope from the evaluator rather than from the module.
            var gs = Module.Equals(module) || module == null ? GlobalScope : module.GlobalScope as Scope;

            if (gs == null)
            {
                return(Disposable.Empty);
            }

            if (node.Parent != null)
            {
                if (!_scopeLookupCache.TryGetValue(node.Parent, out outerScope))
                {
                    outerScope = gs
                                 .TraverseDepthFirst(s => s.Children.OfType <Scope>())
                                 .FirstOrDefault(s => s.Node == node.Parent);
                    _scopeLookupCache[node.Parent] = outerScope;
                }
            }

            outerScope = outerScope ?? gs;
            if (outerScope != null)
            {
                Scope scope;
                if (node is PythonAst)
                {
                    // node points to global scope, it is not a function or a class.
                    scope = gs;
                }
                else
                {
                    scope = outerScope.Children.OfType <Scope>().FirstOrDefault(s => s.Node == node);
                    if (scope == null)
                    {
                        scope = new Scope(node, outerScope, Module);
                        outerScope.AddChildScope(scope);
                        _scopeLookupCache[node] = scope;
                    }
                }

                _openScopes.Push(scope);
                CurrentScope = scope;
            }
            return(new ScopeTracker(this));
        }
Beispiel #2
0
        /// <summary>
        /// Locates and opens existing scope for a node or creates a new scope
        /// as a child of the specified scope. Scope is pushed on the stack
        /// and will be removed when returned the disposable is disposed.
        /// </summary>
        public IDisposable OpenScope(ScopeStatement node, out Scope fromScope)
        {
            fromScope = null;
            if (node.Parent != null)
            {
                fromScope = (GlobalScope as Scope)
                            .TraverseBreadthFirst(s => s.Children.OfType <Scope>())
                            .FirstOrDefault(s => s.Node == node.Parent);
            }

            fromScope = fromScope ?? GlobalScope;
            var scope = fromScope.Children.OfType <Scope>().FirstOrDefault(s => s.Node == node);

            if (scope == null)
            {
                scope = new Scope(node, fromScope, true);
                fromScope.AddChildScope(scope);
            }
            _openScopes.Push(scope);
            CurrentScope = scope;
            return(new ScopeTracker(this));
        }