public CallChain(Node call, CallChain preceding, int limit) { if (limit == 1) { _chain = call; } else { _chain = Enumerable.Repeat(call, 1).Concat(preceding).Concat(EmptyNodes).Take(limit).ToArray(); } }
public override IAnalysisSet Call(Node node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgNames) { var callArgs = ArgumentSet.FromArgs(FunctionDefinition, unit, args, keywordArgNames); if (keywordArgNames != null && keywordArgNames.Any()) { _analysisUnit.AddNamedParameterReferences(unit, keywordArgNames); } var res = DoCall(node, unit, _analysisUnit, callArgs); if (_callsWithClosure != null) { var chain = new CallChain(node, unit, _callDepthLimit); var aggregate = GetAggregate(unit); if (!_callsWithClosure.TryGetValue(aggregate, chain, _callDepthLimit, out var calledUnit) && !unit.ForEval) { _callsSinceLimitChange += 1; if (_callsSinceLimitChange >= ProjectState.Limits.DecreaseCallDepth && _callDepthLimit > 1) { _callDepthLimit -= 1; _callsSinceLimitChange = 0; AnalysisLog.ReduceCallDepth(this, _callsWithClosure.Count, _callDepthLimit); _callsWithClosure.Clear(); chain = chain.Trim(_callDepthLimit); } calledUnit = new FunctionClosureAnalysisUnit(aggregate, (FunctionAnalysisUnit)AnalysisUnit, chain); _callsWithClosure.Add(aggregate, chain, calledUnit); calledUnit.Enqueue(); } Debug.Assert(calledUnit != null || unit.ForEval); res.Split(v => v.IsResolvable(), out _, out var nonLazy); res = DoCall(node, unit, calledUnit, callArgs); res = res.Union(nonLazy); } var context = unit.ForEval ? ResolutionContext.Complete : new ResolutionContext { Caller = this, CallArgs = callArgs, CallSite = node }; var r = res.Resolve(unit, context, out _); return(r); }
public void Add(IVersioned entry, CallChain chain, FunctionAnalysisUnit value) { CallChainEntry entryData; lock (_data) { if (!_data.TryGetValue(entry, out entryData) || entryData.AnalysisVersion != entry.AnalysisVersion) { _data[entry] = entryData = new CallChainEntry( entry.AnalysisVersion, new Dictionary <CallChain, FunctionAnalysisUnit>() ); } } lock (entryData.Calls) { entryData.Calls[chain] = value; } }
public void Add(IPythonProjectEntry entry, CallChain chain, T value) { KeyValuePair <int, Dictionary <CallChain, T> > entryData; lock (_data) { if (!_data.TryGetValue(entry, out entryData) || entryData.Key != entry.AnalysisVersion) { _data[entry] = entryData = new KeyValuePair <int, Dictionary <CallChain, T> >( entry.AnalysisVersion, new Dictionary <CallChain, T>() ); } } lock (entryData.Value) { entryData.Value[chain] = value; } }
public bool TryGetValue(IVersioned entry, CallChain chain, int prefixLength, out FunctionAnalysisUnit value) { value = null; CallChainEntry entryData; lock (_data) { if (!_data.TryGetValue(entry, out entryData)) { return(false); } if (entryData.AnalysisVersion != entry.AnalysisVersion) { _data.Remove(entry); return(false); } } lock (entryData.Calls) { return(entryData.Calls.TryGetValue(chain, out value)); } }
public bool TryGetValue(IPythonProjectEntry entry, CallChain chain, int prefixLength, out T value) { value = default(T); KeyValuePair <int, Dictionary <CallChain, T> > entryData; lock (_data) { if (!_data.TryGetValue(entry, out entryData)) { return(false); } if (entryData.Key != entry.AnalysisVersion) { _data.Remove(entry); return(false); } } lock (entryData.Value) { return(entryData.Value.TryGetValue(chain, out value)); } }
public override IAnalysisSet Call(Node node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgNames) { var callArgs = ArgumentSet.FromArgs(FunctionDefinition, unit, args, keywordArgNames); if (keywordArgNames != null && keywordArgNames.Any()) { _analysisUnit.AddNamedParameterReferences(unit, keywordArgNames); } var res = DoCall(node, unit, _analysisUnit, callArgs); if (_derived != null) { foreach (FunctionInfo derived in _derived) { var derivedResult = derived.DoCall(node, unit, derived._analysisUnit, callArgs); res = res.Union(derivedResult); } } if (_analysisUnit.State.Limits.PropagateParameterTypeToBaseMethods && _analysisUnit.Scope.OuterScope is ClassScope parentClass) { var baseMethods = DDG.LookupBaseMethods(Name, parentClass.Class.Mro, AnalysisUnit.Ast, AnalysisUnit); foreach (FunctionInfo baseMethod in baseMethods.OfType <FunctionInfo>()) { baseMethod.DoCall(node, unit, baseMethod._analysisUnit, callArgs); } } if (_callsWithClosure != null) { var chain = new CallChain(node, unit, _callDepthLimit); var aggregate = GetAggregate(unit); if (!_callsWithClosure.TryGetValue(aggregate, chain, _callDepthLimit, out var calledUnit) && !unit.ForEval) { _callsSinceLimitChange += 1; if (_callsSinceLimitChange >= ProjectState.Limits.DecreaseCallDepth && _callDepthLimit > 1) { _callDepthLimit -= 1; _callsSinceLimitChange = 0; AnalysisLog.ReduceCallDepth(this, _callsWithClosure.Count, _callDepthLimit); _callsWithClosure.Clear(); chain = chain.Trim(_callDepthLimit); } calledUnit = new FunctionClosureAnalysisUnit(aggregate, (FunctionAnalysisUnit)AnalysisUnit, chain); _callsWithClosure.Add(aggregate, chain, calledUnit); calledUnit.Enqueue(); } Debug.Assert(calledUnit != null || unit.ForEval); res.Split(v => v.IsResolvable(), out _, out var nonLazy); res = DoCall(node, unit, calledUnit, callArgs); res = res.Union(nonLazy); } var context = unit.ForEval ? ResolutionContext.Complete : new ResolutionContext { Caller = this, CallArgs = callArgs, CallSite = node }; var r = res.Resolve(unit, context, out _); return(r); }
public override IAnalysisSet Call(Node node, AnalysisUnit unit, IAnalysisSet[] args, NameExpression[] keywordArgNames) { var callArgs = ArgumentSet.FromArgs(FunctionDefinition, unit, args, keywordArgNames); FunctionAnalysisUnit calledUnit; bool updateArguments = true; if (callArgs.Count == 0 || (ProjectState.Limits.UnifyCallsToNew && Name == "__new__") || _callDepthLimit == 0) { calledUnit = (FunctionAnalysisUnit)AnalysisUnit; } else { if (_allCalls == null) { _allCalls = new CallChainSet <FunctionAnalysisUnit>(); } var chain = new CallChain(node, unit, _callDepthLimit); if (!_allCalls.TryGetValue(unit.ProjectEntry, chain, _callDepthLimit, out calledUnit)) { if (unit.ForEval) { // Call expressions that weren't analyzed get the union result // of all calls to this function. var res = AnalysisSet.Empty; foreach (var call in _allCalls.Values) { res = res.Union(call.ReturnValue.TypesNoCopy); } return(res); } else { _callsSinceLimitChange += 1; if (_callsSinceLimitChange >= ProjectState.Limits.DecreaseCallDepth && _callDepthLimit > 1) { _callDepthLimit -= 1; _callsSinceLimitChange = 0; AnalysisLog.ReduceCallDepth(this, _allCalls.Count, _callDepthLimit); _allCalls.Clear(); chain = chain.Trim(_callDepthLimit); } calledUnit = new FunctionAnalysisUnit((FunctionAnalysisUnit)AnalysisUnit, chain, callArgs); _allCalls.Add(unit.ProjectEntry, chain, calledUnit); updateArguments = false; } } } if (updateArguments && calledUnit.UpdateParameters(callArgs)) { AnalysisLog.UpdateUnit(calledUnit); } if (keywordArgNames != null && keywordArgNames.Any()) { calledUnit.AddNamedParameterReferences(unit, keywordArgNames); } calledUnit.ReturnValue.AddDependency(unit); return(calledUnit.ReturnValue.Types); }
public bool Equals(CallChain other) { return(this.SequenceEqual(other)); }
public bool PrefixMatches(CallChain other, int limit) { return(this.Take(limit).SequenceEqual(other.Take(limit))); }