/// <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); }
/// <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); }