Example #1
0
        private void CollectCandidates(ModuleInfo moduleInfo,
                                       string name,
                                       Dictionary <string, ImportInfo> importFullNameMap,
                                       CancellationToken cancellationToken)
        {
            if (!moduleInfo.CheckCircularImports())
            {
                // bail out on circular imports
                return;
            }

            // add non module (imported) member
            AddNonImportedMemberWithName(moduleInfo, name, importFullNameMap);

            // add module (imported) members if it shows up in __all__
            //
            // we are doing recursive dig down rather than just going through all modules loaded linearly
            // since path to how to get to a module is important.
            // for example, "join" is defined in "ntpath" or "macpath" and etc, but users are supposed to
            // use it through "os.path" which will automatically point to right module ex, "ntpath" based on
            // environment rather than "ntpath" directly. if we just go through module in flat list, then
            // we can miss "os.path" since it won't show in the module list.
            // for these modules that are supposed to be used with indirect path (imported name of the module),
            // we need to dig down to collect those with right path.
            foreach (var memberName in GetAllVariables(moduleInfo.Analysis))
            {
                cancellationToken.ThrowIfCancellationRequested();

                var pythonModule = moduleInfo.Module.GetMember(memberName) as IPythonModule;
                if (pythonModule == null)
                {
                    continue;
                }

                var fullName = $"{moduleInfo.FullName}.{memberName}";
                if (string.Equals(memberName, name))
                {
                    // nested module are all imported
                    AddNameParts(fullName, moduleImported: true, memberImported: true, pythonModule, importFullNameMap);
                }

                // make sure we dig down modules only if we can use it from imports
                // for example, user can do "from numpy import char" to import char [defchararray] module
                // but user can not do "from numpy.char import x" since it is not one of known modules to us.
                // in contrast, users can do "from os import path" to import path [ntpath] module
                // but also can do "from os.path import x" since "os.path" is one of known moudles to us.
                var result = AstUtilities.FindImports(
                    moduleInfo.CurrentFileAnalysis.Document.Interpreter.ModuleResolution.CurrentPathResolver,
                    moduleInfo.CurrentFileAnalysis.Document.FilePath,
                    GetRootNames(fullName),
                    dotCount: 0,
                    forceAbsolute: true);

                if (result is ImportNotFound)
                {
                    continue;
                }

                moduleInfo.AddName(memberName);
                CollectCandidates(moduleInfo.With(pythonModule), name, importFullNameMap, cancellationToken);
                moduleInfo.PopName();
            }

            // pop this module out so we can get to this module from
            // different path.
            // ex) A -> B -> [C] and A -> D -> [C]
            moduleInfo.ForgetModule();
        }