/// <summary>
        /// Returns a sequence of possible types associated with the name in the expression evaluators scope.
        /// </summary>
        public IAnalysisSet LookupAnalysisSetByName(Node node, string name, bool addRef = true, bool addDependency = false)
        {
            InterpreterScope createIn = null;
            VariableDef      refs     = null;

            if (_mergeScopes)
            {
                var scope = Scope.EnumerateTowardsGlobal
                            .FirstOrDefault(s => (s == Scope || s.VisibleToChildren) && s.ContainsVariable(name));
                if (scope != null)
                {
                    return(scope.GetMergedVariableTypes(name));
                }
            }
            else
            {
                foreach (var scope in Scope.EnumerateTowardsGlobal)
                {
                    if (scope == Scope || scope.VisibleToChildren)
                    {
                        refs = scope.GetVariable(node, _unit, name, addRef);
                        if (refs != null)
                        {
                            if (addRef)
                            {
                                scope.AddReferenceToLinkedVariables(node, _unit, name);
                            }
                            break;
                        }
                        else if (addRef && createIn == null && scope.ContainsImportStar)
                        {
                            // create the variable so that we can appropriately
                            // add any dependent reads to it.
                            createIn = scope;
                        }
                    }
                }
            }

            if (_unit.ForEval)
            {
                return(refs?.Types ?? ProjectState.BuiltinModule.GetMember(node, _unit, name));
            }

            bool warn = false;
            var  res  = refs?.Types;

            if (res == null)
            {
                // No variable found, so look in builtins
                res = ProjectState.BuiltinModule.GetMember(node, _unit, name);
                if (!res.Any())
                {
                    // No builtin found, so ...
                    if (createIn != null)
                    {
                        // ... create a variable in the best known scope
                        refs = createIn.CreateVariable(node, _unit, name, addRef);
                        res  = refs.Types;
                    }
                    else
                    {
                        switch (name)
                        {
                        // "atom" in Python grammar.
                        case "True":
                        case "False":
                        case "None":
                        case "...":
                            Debug.Fail($"Known good name '{name}' not found in scope");
                            break;

                        default:
                            // ... warn the user
                            warn = true;
                            break;
                        }
                    }
                }
            }

            if (addDependency && refs != null)
            {
                refs.AddDependency(_unit);
            }

            if (warn)
            {
                ProjectState.AddDiagnostic(node, _unit, ErrorMessages.UseBeforeDef(name), DiagnosticSeverity.Warning, ErrorMessages.UseBeforeDefCode);
            }
            else
            {
                ProjectState.ClearDiagnostic(node, _unit, ErrorMessages.UseBeforeDefCode);
            }

            return(res);
        }
Пример #2
0
        /// <summary>
        /// Returns a sequence of possible types associated with the name in the expression evaluators scope.
        /// </summary>
        public IAnalysisSet LookupAnalysisSetByName(Node node, string name, bool addRef = true, bool addDependency = false)
        {
            InterpreterScope createIn = null;
            VariableDef      refs     = null;

            if (_mergeScopes)
            {
                var scope = Scope.EnumerateTowardsGlobal
                            .FirstOrDefault(s => (s == Scope || s.VisibleToChildren) && s.ContainsVariable(name));
                if (scope != null)
                {
                    return(scope.GetMergedVariableTypes(name));
                }
            }
            else
            {
                foreach (var scope in Scope.EnumerateTowardsGlobal)
                {
                    if (scope == Scope || scope.VisibleToChildren)
                    {
                        refs = scope.GetVariable(node, _unit, name, addRef);
                        if (refs != null)
                        {
                            if (addRef)
                            {
                                scope.AddReferenceToLinkedVariables(node, _unit, name);
                            }
                            break;
                        }
                        else if (addRef && createIn == null && scope.ContainsImportStar)
                        {
                            // create the variable so that we can appropriately
                            // add any dependent reads to it.
                            createIn = scope;
                        }
                    }
                }
            }

            if (_unit.ForEval)
            {
                return(refs?.Types ?? ProjectState.BuiltinModule.GetMember(node, _unit, name));
            }

            bool warn = false;
            var  res  = refs?.Types;

            if (res == null)
            {
                // No variable found, so look in builtins
                res = ProjectState.BuiltinModule.GetMember(node, _unit, name);
                if (!res.Any())
                {
                    // No builtin found, so ...
                    if (createIn != null)
                    {
                        // ... create a variable in the best known scope
                        refs = createIn.CreateVariable(node, _unit, name, addRef);
                        res  = refs.Types;
                    }
                    else
                    {
                        // ... warn the user
                        warn = true;
                    }
                }
            }
            else if (!res.Any() && !refs.IsAssigned)
            {
                // Variable has no values, so if we also don't know about any
                // definitions then warn.
                warn = true;
            }

            if (addDependency && refs != null)
            {
                refs.AddDependency(_unit);
            }

            if (warn)
            {
                ProjectState.AddDiagnostic(node, _unit, ErrorMessages.UsedBeforeAssignment(name), DiagnosticSeverity.Warning, ErrorMessages.UsedBeforeAssignmentCode);
            }
            else
            {
                ProjectState.ClearDiagnostic(node, _unit, ErrorMessages.UsedBeforeAssignmentCode);
            }

            return(res);
        }