internal void AnalyzeDefaultParameters(DDG ddg) { VariableDef param; for (int i = 0; i < Ast.ParametersInternal.Length; ++i) { var p = Ast.ParametersInternal[i]; if (p.Annotation != null) { var val = ddg._eval.EvaluateAnnotation(p.Annotation); if (val?.Any() == true && Scope.TryGetVariable(p.Name, out param)) { param.AddTypes(this, val, false); } } if (p.DefaultValue != null && p.Kind != ParameterKind.List && p.Kind != ParameterKind.Dictionary && Scope.TryGetVariable(p.Name, out param)) { var val = ddg._eval.Evaluate(p.DefaultValue); if (val != null) { param.AddTypes(this, val, false); } } } if (Ast.ReturnAnnotation != null) { var ann = ddg._eval.EvaluateAnnotation(Ast.ReturnAnnotation); var resType = AnalysisSet.Empty; if (Ast.IsGenerator && ann.Split <GeneratorInfo>(out var gens, out resType)) { var gen = ((FunctionScope)Scope).Generator; foreach (var g in gens) { g.Yields.CopyTo(gen.Yields); g.Sends.CopyTo(gen.Sends); g.Returns.CopyTo(gen.Returns); } } ((FunctionScope)Scope).AddReturnTypes( Ast.ReturnAnnotation, ddg._unit, resType ); } }
internal override void AnalyzeWorker(DDG ddg, CancellationToken cancel) { // Resolve default parameters and decorators in the outer scope but // continue to associate changes with this unit. ddg.Scope = _declUnit.Scope; AnalyzeDefaultParameters(ddg); if (_decoratorCalls != null) { ProcessFunctionDecorators(ddg); } // Set the scope to within the function ddg.Scope = Scope; Ast.Body.Walk(ddg); }
internal override void AnalyzeWorker(DDG ddg, CancellationToken cancel) { // Resolve default parameters and decorators in the outer scope but // continue to associate changes with this unit. ddg.Scope = _declUnit.Scope; AnalyzeDefaultParameters(ddg); var funcType = ProcessFunctionDecorators(ddg); EnsureParameterZero(); _declUnit.Scope.AddLocatedVariable(Ast.Name, Ast.NameExpression, this); // Set the scope to within the function ddg.Scope = Scope; Ast.Body.Walk(ddg); _declUnit.Scope.AssignVariable(Ast.Name, Ast.NameExpression, this, funcType); }
internal void AnalyzeDefaultParameters(DDG ddg) { VariableDef param; for (int i = 0; i < Ast.Parameters.Count; ++i) { var p = Ast.Parameters[i]; ddg._eval.EvaluateMaybeNull(p.Annotation); if (p.DefaultValue != null && p.Kind != ParameterKind.List && p.Kind != ParameterKind.Dictionary && Scope.TryGetVariable(p.Name, out param)) { var val = ddg._eval.Evaluate(p.DefaultValue); if (val != null) { param.AddTypes(this, val, false); } } } ddg._eval.EvaluateMaybeNull(Ast.ReturnAnnotation); }
internal void ProcessFunctionDecorators(DDG ddg) { if (Ast.Decorators != null) { var types = Function.SelfSet; Expression expr = Ast.NameExpression; foreach (var d in Ast.Decorators.DecoratorsInternal) { if (d != null) { var decorator = ddg._eval.Evaluate(d); if (decorator.Contains(State.ClassInfos[BuiltinTypeId.Property])) { Function.IsProperty = true; } else if (decorator.Contains(State.ClassInfos[BuiltinTypeId.StaticMethod])) { // TODO: Warn if IsClassMethod is set Function.IsStatic = true; } else if (decorator.Contains(State.ClassInfos[BuiltinTypeId.ClassMethod])) { // TODO: Warn if IsStatic is set Function.IsClassMethod = true; } else { Expression nextExpr; if (!_decoratorCalls.TryGetValue(d, out nextExpr)) { nextExpr = _decoratorCalls[d] = new CallExpression(d, new[] { new Arg(expr) }); } expr = nextExpr; var decorated = AnalysisSet.Empty; bool anyResults = false; foreach (var ns in decorator) { var fd = ns as FunctionInfo; if (fd != null && Scope.EnumerateTowardsGlobal.Any(s => s.AnalysisValue == fd)) { continue; } decorated = decorated.Union(ns.Call(expr, this, new[] { types }, ExpressionEvaluator.EmptyNames)); anyResults = true; } // If processing decorators, update the current // function type. Otherwise, we are acting as if // each decorator returns the function unmodified. if (ddg.ProjectState.Limits.ProcessCustomDecorators && anyResults) { types = decorated; } } } } ddg.Scope.AddLocatedVariable(Ast.Name, Ast.NameExpression, this).AddTypes(this, types); } if (!Function.IsStatic && Ast.ParametersInternal.Length > 0) { VariableDef param; IAnalysisSet firstParam; var clsScope = ddg.Scope as ClassScope; if (clsScope == null) { firstParam = Function.IsClassMethod ? State.ClassInfos[BuiltinTypeId.Type].SelfSet : AnalysisSet.Empty; } else { firstParam = Function.IsClassMethod ? clsScope.Class.SelfSet : clsScope.Class.Instance.SelfSet; } if (Scope.TryGetVariable(Ast.ParametersInternal[0].Name, out param)) { param.AddTypes(this, firstParam, false); } } }
internal void AnalyzeDefaultParameters(DDG ddg) { VariableDef param; var scope = (FunctionScope)Scope; for (int i = 0; i < Ast.ParametersInternal.Length; ++i) { var p = Ast.ParametersInternal[i]; if (p.Annotation != null) { var val = ddg._eval.EvaluateAnnotation(p.Annotation); if (val?.Any() == true && Scope.TryGetVariable(p.Name, out param)) { param.AddTypes(this, val, false); var vd = scope.GetParameter(p.Name); if (vd != null && vd != param) { vd.AddTypes(this, val, false); } } } if (p.DefaultValue != null && p.Kind != ParameterKind.List && p.Kind != ParameterKind.Dictionary && Scope.TryGetVariable(p.Name, out param)) { var val = ddg._eval.Evaluate(p.DefaultValue); if (val != null) { param.AddTypes(this, val, false); var vd = scope.GetParameter(p.Name); if (vd != null && vd != param) { vd.AddTypes(this, val, false); } } } } if (Ast.ReturnAnnotation != null) { var ann = ddg._eval.EvaluateAnnotation(Ast.ReturnAnnotation); var resType = ann; if (Ast.IsGenerator) { if (ann.Split <ProtocolInfo>(out var gens, out resType)) { var gen = ((FunctionScope)Scope).Generator; foreach (var g in gens.SelectMany(p => p.GetProtocols <GeneratorProtocol>())) { gen.Yields.AddTypes(ProjectEntry, g.Yielded); gen.Sends.AddTypes(ProjectEntry, g.Sent); gen.Returns.AddTypes(ProjectEntry, g.Returned); } } } else { ((FunctionScope)Scope).AddReturnTypes( Ast.ReturnAnnotation, ddg._unit, resType ); } } }
internal IAnalysisSet ProcessFunctionDecorators(DDG ddg) { var types = Function.SelfSet; if (Ast.Decorators != null) { Expression expr = Ast.NameExpression; foreach (var d in Ast.Decorators.DecoratorsInternal) { if (d != null) { var decorator = ddg._eval.Evaluate(d); if (decorator.Contains(State.ClassInfos[BuiltinTypeId.Property])) { Function.IsProperty = true; } else if (decorator.Contains(State.ClassInfos[BuiltinTypeId.StaticMethod])) { // TODO: Warn if IsClassMethod is set Function.IsStatic = true; } else if (decorator.Contains(State.ClassInfos[BuiltinTypeId.ClassMethod])) { // TODO: Warn if IsStatic is set Function.IsClassMethod = true; } else if (ProcessAbstractDecorators(decorator)) { // No-op } else { Expression nextExpr; if (!_decoratorCalls.TryGetValue(d, out nextExpr)) { nextExpr = _decoratorCalls[d] = new CallExpression(d, new[] { new Arg(expr) }); nextExpr.SetLoc(d.IndexSpan); } expr = nextExpr; var decorated = AnalysisSet.Empty; bool anyResults = false; foreach (var ns in decorator) { var fd = ns as FunctionInfo; if (fd != null && Scope.EnumerateTowardsGlobal.Any(s => s.AnalysisValue == fd)) { continue; } decorated = decorated.Union(ns.Call(expr, this, new[] { types }, ExpressionEvaluator.EmptyNames)); anyResults = true; } // If processing decorators, update the current // function type. Otherwise, we are acting as if // each decorator returns the function unmodified. if (ddg.ProjectState.Limits.ProcessCustomDecorators && anyResults) { types = decorated; } } } } } return(types); }
internal void ProcessFunctionDecorators(DDG ddg) { if (Ast.Decorators != null) { var types = Function.SelfSet; Expression expr = Ast.NameExpression; foreach (var d in Ast.Decorators.Decorators) { if (d != null) { var decorator = ddg._eval.Evaluate(d); if (decorator.Contains(ProjectState.ClassInfos[BuiltinTypeId.Property])) { Function.IsProperty = true; } else if (decorator.Contains(ProjectState.ClassInfos[BuiltinTypeId.StaticMethod])) { // TODO: Warn if IsClassMethod is set Function.IsStatic = true; } else if (decorator.Contains(ProjectState.ClassInfos[BuiltinTypeId.ClassMethod])) { // TODO: Warn if IsStatic is set Function.IsClassMethod = true; } else { Expression nextExpr; if (!_decoratorCalls.TryGetValue(d, out nextExpr)) { nextExpr = _decoratorCalls[d] = new CallExpression(d, new[] { new Arg(expr) }); } expr = nextExpr; types = decorator.Call(expr, this, new[] { types }, ExpressionEvaluator.EmptyNames); } } } ddg.Scope.AddLocatedVariable(Ast.Name, Ast.NameExpression, this).AddTypes(this, types); } if (!Function.IsStatic && Ast.Parameters.Count > 0) { VariableDef param; IAnalysisSet firstParam; var clsScope = ddg.Scope as ClassScope; if (clsScope == null) { firstParam = Function.IsClassMethod ? ProjectState.ClassInfos[BuiltinTypeId.Type].SelfSet : AnalysisSet.Empty; } else { firstParam = Function.IsClassMethod ? clsScope.Class.SelfSet : clsScope.Class.Instance.SelfSet; } if (Scope.Variables.TryGetValue(Ast.Parameters[0].Name, out param)) { param.AddTypes(this, firstParam, false); } } }