Beispiel #1
0
        private void Parse(bool enqueueOnly, CancellationToken cancel)
        {
            PythonAst       tree;
            IAnalysisCookie cookie;

            GetTreeAndCookie(out tree, out cookie);
            if (tree == null)
            {
                return;
            }

            var oldParent = _myScope.ParentPackage;

            if (_filePath != null)
            {
                ProjectState.ModulesByFilename[_filePath] = _myScope;
            }

            if (oldParent != null)
            {
                // update us in our parent package
                oldParent.AddChildPackage(_myScope, _unit);
            }
            else if (_filePath != null)
            {
                // we need to check and see if our parent is a package for the case where we're adding a new
                // file but not re-analyzing our parent package.
                string parentFilename;
                if (ModulePath.IsInitPyFile(_filePath))
                {
                    // subpackage
                    parentFilename = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(_filePath)), "__init__.py");
                }
                else
                {
                    // just a module
                    parentFilename = Path.Combine(Path.GetDirectoryName(_filePath), "__init__.py");
                }

                ModuleInfo parentPackage;
                if (ProjectState.ModulesByFilename.TryGetValue(parentFilename, out parentPackage))
                {
                    parentPackage.AddChildPackage(_myScope, _unit);
                }
            }

            _unit = new AnalysisUnit(tree, _myScope.Scope);
            AnalysisLog.NewUnit(_unit);

            foreach (var value in MyScope.Scope.AllVariables)
            {
                value.Value.EnqueueDependents();
            }

            MyScope.Scope.Children.Clear();
            MyScope.Scope.ClearNodeScopes();
            MyScope.Scope.ClearNodeValues();
            MyScope.ClearUnresolvedModules();

            // collect top-level definitions first
            var walker = new OverviewWalker(this, _unit, tree);

            tree.Walk(walker);

            _myScope.Specialize();

            // It may be that we have analyzed some child packages of this package already, but because it wasn't analyzed,
            // the children were not registered. To handle this possibility, scan analyzed packages for children of this
            // package (checked by module name first, then sanity-checked by path), and register any that match.
            if (ModulePath.IsInitPyFile(_filePath))
            {
                string pathPrefix = Path.GetDirectoryName(_filePath) + "\\";
                var    children   =
                    from pair in _projectState.ModulesByFilename
                    // Is the candidate child package in a subdirectory of our package?
                    let fileName = pair.Key
                                   where fileName.StartsWith(pathPrefix)
                                   let moduleName = pair.Value.Name
                                                    // Is the full name of the candidate child package qualified with the name of our package?
                                                    let lastDot = moduleName.LastIndexOf('.')
                                                                  where lastDot > 0
                                                                  let parentModuleName = moduleName.Substring(0, lastDot)
                                                                                         where parentModuleName == _myScope.Name
                                                                                         select pair.Value;
                foreach (var child in children)
                {
                    _myScope.AddChildPackage(child, _unit);
                }
            }

            _unit.Enqueue();

            if (!enqueueOnly)
            {
                _projectState.AnalyzeQueuedEntries(cancel);
            }

            // publish the analysis now that it's complete/running
            _currentAnalysis = new ModuleAnalysis(
                _unit,
                ((ModuleScope)_unit.Scope).CloneForPublish()
                );
        }
Beispiel #2
0
        private void Parse(bool enqueueOnly, CancellationToken cancel)
        {
#if DEBUG
            Debug.Assert(Monitor.IsEntered(this));
#endif
            var parse  = GetCurrentParse();
            var tree   = parse?.Tree;
            var cookie = parse?.Cookie;
            if (tree == null)
            {
                return;
            }

            var oldParent = MyScope.ParentPackage;
            if (FilePath != null)
            {
                ProjectState.ModulesByFilename[FilePath] = MyScope;
            }

            if (oldParent != null)
            {
                // update us in our parent package
                oldParent.AddChildPackage(MyScope, _unit);
            }
            else if (FilePath != null)
            {
                // we need to check and see if our parent is a package for the case where we're adding a new
                // file but not re-analyzing our parent package.
                string parentFilename;
                if (ModulePath.IsInitPyFile(FilePath))
                {
                    // subpackage
                    parentFilename = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(FilePath)), "__init__.py");
                }
                else
                {
                    // just a module
                    parentFilename = Path.Combine(Path.GetDirectoryName(FilePath), "__init__.py");
                }

                if (ProjectState.ModulesByFilename.TryGetValue(parentFilename, out var parentPackage))
                {
                    parentPackage.AddChildPackage(MyScope, _unit);
                }
            }

            _unit = new AnalysisUnit(tree, MyScope.Scope);
            AnalysisLog.NewUnit(_unit);

            MyScope.Scope.Children = new List <InterpreterScope>();
            MyScope.Scope.ClearNodeScopes();
            MyScope.Scope.ClearNodeValues();
            MyScope.Scope.ClearLinkedVariables();
            MyScope.Scope.ClearVariables();
            MyScope.ClearReferencedModules();
            MyScope.ClearUnresolvedModules();
            _unit.State.ClearDiagnostics(this);

            MyScope.EnsureModuleVariables(_unit.State);

            foreach (var value in MyScope.Scope.AllVariables)
            {
                value.Value.EnqueueDependents();
            }

            // collect top-level definitions first
            var walker = new OverviewWalker(this, _unit, tree);
            tree.Walk(walker);

            MyScope.Specialize();

            // It may be that we have analyzed some child packages of this package already, but because it wasn't analyzed,
            // the children were not registered. To handle this possibility, scan analyzed packages for children of this
            // package (checked by module name first, then sanity-checked by path), and register any that match.
            if (ModulePath.IsInitPyFile(FilePath))
            {
                string pathPrefix = PathUtils.EnsureEndSeparator(Path.GetDirectoryName(FilePath));
                var    children   =
                    from pair in ProjectState.ModulesByFilename
                    // Is the candidate child package in a subdirectory of our package?
                    let fileName = pair.Key
                                   where fileName.StartsWithOrdinal(pathPrefix, ignoreCase: true)
                                   let moduleName = pair.Value.Name
                                                    // Is the full name of the candidate child package qualified with the name of our package?
                                                    let lastDot = moduleName.LastIndexOf('.')
                                                                  where lastDot > 0
                                                                  let parentModuleName = moduleName.Substring(0, lastDot)
                                                                                         where parentModuleName == MyScope.Name
                                                                                         select pair.Value;
                foreach (var child in children)
                {
                    MyScope.AddChildPackage(child, _unit);
                }
            }

            _unit.Enqueue();

            if (!enqueueOnly)
            {
                ProjectState.AnalyzeQueuedEntries(cancel);
            }

            // publish the analysis now that it's complete/running
            Analysis = new ModuleAnalysis(
                _unit,
                ((ModuleScope)_unit.Scope).CloneForPublish(),
                DocumentUri,
                AnalysisVersion
                );
        }
Beispiel #3
0
        /// <summary>
        /// Returns a sequence of candidate absolute module names for the given
        /// modules.
        /// </summary>
        /// <param name="projectEntry">
        /// The project entry that is importing the module.
        /// </param>
        /// <param name="relativeModuleName">
        /// A dotted name identifying the path to the module.
        /// </param>
        /// <returns>
        /// A sequence of strings representing the absolute names of the module
        /// in order of precedence.
        /// </returns>
        internal static IEnumerable <string> ResolvePotentialModuleNames(
            IPythonProjectEntry projectEntry,
            string relativeModuleName,
            bool absoluteImports
            )
        {
            string importingFrom = null;

            if (projectEntry != null)
            {
                importingFrom = projectEntry.ModuleName;
                if (ModulePath.IsInitPyFile(projectEntry.FilePath))
                {
                    if (string.IsNullOrEmpty(importingFrom))
                    {
                        importingFrom = "__init__";
                    }
                    else
                    {
                        importingFrom += ".__init__";
                    }
                }
            }

            if (string.IsNullOrEmpty(relativeModuleName))
            {
                yield break;
            }

            // Handle relative module names
            if (relativeModuleName.FirstOrDefault() == '.')
            {
                if (string.IsNullOrEmpty(importingFrom))
                {
                    // No source to import relative to.
                    yield break;
                }

                var prefix = importingFrom.Split('.');

                if (relativeModuleName.LastOrDefault() == '.')
                {
                    // Last part empty means the whole name is dots, so there's
                    // nothing to concatenate.
                    yield return(string.Join(".", prefix.Take(prefix.Length - relativeModuleName.Length)));
                }
                else
                {
                    var suffix   = relativeModuleName.Split('.');
                    var dotCount = suffix.TakeWhile(bit => string.IsNullOrEmpty(bit)).Count();
                    if (dotCount < prefix.Length)
                    {
                        // If we have as many dots as prefix parts, the entire
                        // name will disappear. Despite what PEP 328 says, in
                        // reality this means the import will fail.
                        yield return(string.Join(".", prefix.Take(prefix.Length - dotCount).Concat(suffix.Skip(dotCount))));
                    }
                }
                yield break;
            }

            // The two possible names that can be imported here are:
            // * relativeModuleName
            // * importingFrom.relativeModuleName
            // and the order they are returned depends on whether
            // absolute_import is enabled or not.

            // With absolute_import, we treat the name as complete first.
            if (absoluteImports)
            {
                yield return(relativeModuleName);
            }

            if (!string.IsNullOrEmpty(importingFrom))
            {
                var prefix = importingFrom.Split('.');

                if (prefix.Length > 1)
                {
                    var adjacentModuleName = string.Join(".", prefix.Take(prefix.Length - 1)) + "." + relativeModuleName;
                    yield return(adjacentModuleName);
                }
            }

            // Without absolute_import, we treat the name as complete last.
            if (!absoluteImports)
            {
                yield return(relativeModuleName);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Returns a sequence of candidate absolute module names for the given
        /// modules.
        /// </summary>
        /// <param name="importingFromModuleName">
        /// The module that is importing the module.
        /// </param>
        /// <param name="importingFromFilePath">
        /// The path to the file that is importing the module.
        /// </param>
        /// <param name="relativeModuleName">
        /// A dotted name identifying the path to the module.
        /// </param>
        /// <returns>
        /// A sequence of strings representing the absolute names of the module
        /// in order of precedence.
        /// </returns>
        internal static IEnumerable <string> ResolvePotentialModuleNames(
            string importingFromModuleName,
            string importingFromFilePath,
            string relativeModuleName,
            bool absoluteImports
            )
        {
            string importingFrom = string.Empty;

            if (!string.IsNullOrEmpty(importingFromModuleName))
            {
                importingFrom = importingFromModuleName;
                if (!string.IsNullOrEmpty(importingFromFilePath) && ModulePath.IsInitPyFile(importingFromFilePath))
                {
                    if (string.IsNullOrEmpty(importingFrom))
                    {
                        importingFrom = "__init__";
                    }
                    else
                    {
                        importingFrom += ".__init__";
                    }
                }
            }

            if (string.IsNullOrEmpty(relativeModuleName))
            {
                yield break;
            }

            // Handle relative module names
            if (relativeModuleName.FirstOrDefault() == '.')
            {
                var fullName = GetModuleFullName(importingFrom, relativeModuleName);
                if (!fullName.StartsWithOrdinal(".") && !fullName.EndsWithOrdinal("."))
                {
                    yield return(fullName);
                }
                yield break;
            }

            // The two possible names that can be imported here are:
            // * relativeModuleName
            // * importingFrom.relativeModuleName
            // and the order they are returned depends on whether
            // absolute_import is enabled or not.

            // Assume trailing dots are not part of the import
            relativeModuleName = relativeModuleName.TrimEnd('.');

            // With absolute_import, we treat the name as complete first.
            if (absoluteImports)
            {
                yield return(relativeModuleName);
            }

            if (!string.IsNullOrEmpty(importingFrom))
            {
                var prefix = importingFrom.Split('.');

                if (prefix.Length > 1)
                {
                    var adjacentModuleName = string.Join(".", prefix.Take(prefix.Length - 1)) + "." + relativeModuleName;
                    yield return(adjacentModuleName);
                }
            }

            // Without absolute_import, we treat the name as complete last.
            if (!absoluteImports)
            {
                yield return(relativeModuleName);
            }
        }