Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 3670ed9

Browse files
author
MikhailArkhipov
committed
OVerload types handling
1 parent 7973ad1 commit 3670ed9

8 files changed

Lines changed: 110 additions & 87 deletions

File tree

src/Analysis/Engine/Impl/AnalysisSet.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,9 +593,7 @@ public bool Equals(AnalysisValue x, AnalysisValue y) {
593593
return (x == null) ? (y == null) : x.UnionEquals(y, Strength);
594594
}
595595

596-
public int GetHashCode(AnalysisValue obj) {
597-
return (obj == null) ? 0 : obj.UnionHashCode(Strength);
598-
}
596+
public int GetHashCode(AnalysisValue obj) => obj == null ? 0 : obj.UnionHashCode(Strength);
599597

600598
public AnalysisValue MergeTypes(AnalysisValue x, AnalysisValue y, out bool wasChanged) {
601599
if (Object.ReferenceEquals(x, y)) {

src/Analysis/Engine/Impl/OverloadResult.cs

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,32 @@
2020
using System.Text;
2121
using System.Threading.Tasks;
2222
using Microsoft.PythonTools.Analysis.Infrastructure;
23+
using Microsoft.PythonTools.Analysis.Values;
2324
using Microsoft.PythonTools.Interpreter;
2425

2526
namespace Microsoft.PythonTools.Analysis {
2627
public class OverloadResult : IOverloadResult {
2728
private readonly ParameterResult[] _parameters;
28-
private readonly string[] _returnType;
29+
private readonly IAnalysisSet _returnTypes;
2930

30-
public OverloadResult(ParameterResult[] parameters, string name, string documentation, IEnumerable<string> returnType) {
31+
public OverloadResult(ParameterResult[] parameters, string name, string documentation, IAnalysisSet returnTypes) {
3132
_parameters = parameters;
3233
Name = name;
3334
Documentation = documentation;
34-
_returnType = returnType.MaybeEnumerate().ToArray();
35+
_returnTypes = returnTypes;
3536
}
3637

3738
public string Name { get; }
38-
public virtual IReadOnlyList<string> ReturnType { get { return _returnType; } }
39+
public virtual IReadOnlyList<string> ReturnType => _returnTypes.Select(t => t.Name).ToArray();
40+
public virtual IAnalysisSet ReturnTypes => _returnTypes;
3941
public virtual string Documentation { get; }
40-
public virtual ParameterResult[] Parameters { get { return _parameters; } }
42+
public virtual ParameterResult[] Parameters => _parameters;
4143

42-
internal virtual OverloadResult WithNewParameters(ParameterResult[] newParameters) {
43-
return new OverloadResult(newParameters, Name, Documentation, ReturnType);
44-
}
44+
internal virtual OverloadResult WithNewParameters(ParameterResult[] newParameters)
45+
=> new OverloadResult(newParameters, Name, Documentation, ReturnTypes);
4546

46-
internal virtual OverloadResult WithoutLeadingParameters(int skipCount = 1) {
47-
return new OverloadResult(_parameters.Skip(skipCount).ToArray(), Name, Documentation, _returnType);
48-
}
47+
internal virtual OverloadResult WithoutLeadingParameters(int skipCount = 1)
48+
=> new OverloadResult(_parameters.Skip(skipCount).ToArray(), Name, Documentation, _returnTypes);
4949

5050
private static string Longest(string x, string y) {
5151
if (x == null) {
@@ -84,11 +84,8 @@ private static IEnumerable<string> CommaSplit(string x) {
8484
}
8585
}
8686

87-
private static string Merge(string x, string y) {
88-
return string.Join(", ",
89-
CommaSplit(x).Concat(CommaSplit(y)).OrderBy(n => n).Distinct()
90-
);
91-
}
87+
private static string Merge(string x, string y)
88+
=> string.Join(", ", CommaSplit(x).Concat(CommaSplit(y)).OrderBy(n => n).Distinct());
9289

9390
public static OverloadResult Merge(IEnumerable<OverloadResult> overloads) {
9491
overloads = overloads.ToArray();
@@ -117,18 +114,29 @@ public static OverloadResult Merge(IEnumerable<OverloadResult> overloads) {
117114

118115
return res;
119116
});
120-
var returnType = overloads.SelectMany(o => o.ReturnType).Distinct();
121117

122-
return new OverloadResult(parameters, name, doc, returnType);
118+
var returnTypes = overloads.SelectMany(o => o.ReturnTypes).Distinct();
119+
return new OverloadResult(parameters, name, doc, AnalysisSet.Create(returnTypes));
123120
}
124121

125122
public override string ToString() {
126-
return "{0}({1})->[{2}]{3}".FormatInvariant(
127-
Name,
128-
string.Join(",", Parameters.Select(p => "{0}{1}:{2}={3}".FormatInvariant(p.Name, p.IsOptional ? "?" : "", p.Type ?? "", p.DefaultValue ?? ""))),
129-
string.Join(",", ReturnType.OrderBy(k => k)),
130-
string.IsNullOrEmpty(Documentation) ? "" : ("'''{0}'''".FormatInvariant(Documentation))
123+
var parameters = string.Join(", ",
124+
Parameters.Select(p => "{0}{1}:{2}{3}{4}"
125+
.FormatInvariant(p.Name,
126+
p.IsOptional ? "?" : string.Empty,
127+
p.Type ?? string.Empty,
128+
p.DefaultValue != null ? "=" : string.Empty,
129+
p.DefaultValue ?? string.Empty))
130+
).TrimEnd();
131+
132+
var returnType = "{0}{1}{2}".FormatInvariant(
133+
ReturnType.Count > 1 ? "[" : string.Empty,
134+
ReturnType.Count > 0 ? string.Join(",", ReturnType.OrderBy(k => k)) : "None",
135+
ReturnType.Count > 1 ? "]" : string.Empty
131136
);
137+
138+
var doc = string.IsNullOrEmpty(Documentation) ? "" : "'''{0}'''".FormatInvariant(Documentation);
139+
return "{0}({1}) -> {2}{3}".FormatInvariant(Name, parameters, returnType, doc);
132140
}
133141
}
134142

@@ -138,7 +146,7 @@ class AccumulatedOverloadResult {
138146
private string[] _pnames;
139147
private IAnalysisSet[] _ptypes;
140148
private string[] _pdefaults;
141-
private readonly HashSet<string> _rtypes;
149+
private IAnalysisSet _rtypes;
142150

143151
public AccumulatedOverloadResult(string name, string documentation, int parameters) {
144152
_name = name;
@@ -147,14 +155,13 @@ public AccumulatedOverloadResult(string name, string documentation, int paramete
147155
_ptypes = new IAnalysisSet[parameters];
148156
_pdefaults = new string[parameters];
149157
ParameterCount = parameters;
150-
_rtypes = new HashSet<string>();
158+
_rtypes = AnalysisSet.Empty;
151159
}
152160

153161
public int ParameterCount { get; }
154162

155-
private bool AreNullOrEqual(string x, string y) {
156-
return string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y) || string.Equals(x, y, StringComparison.Ordinal);
157-
}
163+
private bool AreNullOrEqual(string x, string y) =>
164+
string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y) || string.Equals(x, y, StringComparison.Ordinal);
158165

159166
private bool AreNullOrEqual(IAnalysisSet x, IAnalysisSet y) {
160167
return x == null || x.IsObjectOrUnknown() ||
@@ -174,15 +181,15 @@ private string ChooseBest(string x, string y) {
174181

175182
private IAnalysisSet ChooseBest(IAnalysisSet x, IAnalysisSet y) {
176183
if (x == null || x.IsObjectOrUnknown()) {
177-
return (y == null || y.IsObjectOrUnknown()) ? AnalysisSet.Empty : y;
184+
return (y == null) ? AnalysisSet.Empty : y;
178185
}
179186
if (y == null || y.IsObjectOrUnknown()) {
180-
return AnalysisSet.Empty;
187+
return null;
181188
}
182-
return x.Union(y);
189+
return MergeTypes(x, y);
183190
}
184191

185-
public bool TryAddOverload(string name, string documentation, string[] names, IAnalysisSet[] types, string[] defaults, IEnumerable<string> returnTypes) {
192+
public bool TryAddOverload(string name, string documentation, string[] names, IAnalysisSet[] types, string[] defaults, IAnalysisSet returnTypes) {
186193
if (names.Length != _pnames.Length || types.Length != _ptypes.Length) {
187194
return false;
188195
}
@@ -210,7 +217,7 @@ public bool TryAddOverload(string name, string documentation, string[] names, IA
210217
}
211218

212219
if (returnTypes != null) {
213-
_rtypes.UnionWith(returnTypes);
220+
_rtypes = ChooseBest(_rtypes, returnTypes);
214221
}
215222

216223
return true;
@@ -234,6 +241,27 @@ public OverloadResult ToOverloadResult() {
234241
}
235242
return new OverloadResult(parameters, _name, _doc, _rtypes);
236243
}
244+
245+
private IAnalysisSet MergeTypes(IAnalysisSet x, IAnalysisSet y) {
246+
// Merge types so we get simple parameter description such as
247+
// list[int] rather than duplicates such as list[int],list[int, int, int].
248+
var cmp = UnionComparer.Instances[1];
249+
var xA = x.ToArray();
250+
var yA = y.ToArray();
251+
var mergedValues = new List<AnalysisValue>();
252+
for (var i = 0; i < xA.Length; i++) {
253+
// Order types for merging in the order of description length
254+
// so more complex type would possibly fold into the simpler type
255+
// such as list[int, int, int] will fold into the list[int].
256+
257+
// TODO: this is not bulletproof.
258+
// For example, it will merge user type derived from int into the int.
259+
var xd = string.Join(",", xA[i].GetShortDescriptions());
260+
var yd = string.Join(",", yA[i].GetShortDescriptions());
261+
mergedValues.Add(xd.Length < yd.Length ? cmp.MergeTypes(xA[i], yA[i], out _) : cmp.MergeTypes(yA[i], xA[i], out _));
262+
}
263+
return AnalysisSet.CreateUnion(mergedValues, cmp);
264+
}
237265
}
238266

239267
class BuiltinFunctionOverloadResult : OverloadResult {
@@ -245,7 +273,6 @@ class BuiltinFunctionOverloadResult : OverloadResult {
245273
private readonly Func<string> _fallbackDoc;
246274
private string _doc;
247275
private IReadOnlyList<string> _returnTypes;
248-
private static readonly string _calculating = "Documentation is still being calculated, please try again soon.";
249276

250277
// Used by ToString to ensure docs have completed
251278
private Task _docTask;
@@ -306,7 +333,7 @@ public override string Documentation {
306333

307334
private void Calculate() {
308335
// initially fill in w/ a string saying we don't yet have the documentation
309-
_doc = _calculating;
336+
_doc = Resources.CalculatingDocumentation;
310337
_docTask = Task.Factory.StartNew(DocCalculator);
311338
}
312339

src/Analysis/Engine/Impl/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Analysis/Engine/Impl/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,7 @@
300300
<value># Sets the width for wrapping comments
301301
# and documentation strings.</value>
302302
</data>
303+
<data name="CalculatingDocumentation" xml:space="preserve">
304+
<value>Documentation is still being calculated, please try again soon.</value>
305+
</data>
303306
</root>

src/Analysis/Engine/Impl/Values/ClassInfo.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public override IEnumerable<OverloadResult> Overloads {
271271
overload.Parameters,
272272
ClassDefinition.Name,
273273
overload.Documentation,
274-
overload.ReturnType
274+
overload.ReturnTypes
275275
)
276276
);
277277
}
@@ -289,7 +289,7 @@ public override IEnumerable<OverloadResult> Overloads {
289289
new ParameterResult[0],
290290
ClassDefinition.Name,
291291
ClassDefinition.Body.Documentation.TrimDocumentation(),
292-
new[] { ShortDescription }
292+
AnalysisSet.Empty
293293
));
294294
}
295295

@@ -303,8 +303,8 @@ private OverloadResult GetNewOverloadResult(OverloadResult overload) {
303303
return new OverloadResult(
304304
overload.Parameters.RemoveFirst(),
305305
ClassDefinition.Name,
306-
String.IsNullOrEmpty(doc) ? Documentation : doc,
307-
overload.ReturnType
306+
string.IsNullOrEmpty(doc) ? Documentation : doc,
307+
overload.ReturnTypes
308308
);
309309
}
310310

@@ -313,8 +313,8 @@ private OverloadResult GetInitOverloadResult(OverloadResult overload) {
313313
return new OverloadResult(
314314
overload.Parameters.RemoveFirst(),
315315
ClassDefinition.Name,
316-
String.IsNullOrEmpty(doc) ? Documentation : doc,
317-
overload.ReturnType
316+
string.IsNullOrEmpty(doc) ? Documentation : doc,
317+
overload.ReturnTypes
318318
);
319319
}
320320

src/Analysis/Engine/Impl/Values/FunctionInfo.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,13 +485,12 @@ public override IEnumerable<OverloadResult> Overloads {
485485
LazyCallArgs = new Lazy<ArgumentSet>(() => new ArgumentSet(vars, null, null, null)),
486486
ResolveFully = true
487487
}, out _)
488-
.GetShortDescriptions()
489488
.ToArray();
490489

491490
bool needNewSet = true;
492491
foreach (var set in parameterSets) {
493492
if (set.ParameterCount == names.Length) {
494-
if (set.TryAddOverload(null, null, names, vars, defaults, rtypes)) {
493+
if (set.TryAddOverload(null, null, names, vars, defaults, AnalysisSet.Create(rtypes))) {
495494
needNewSet = false;
496495
break;
497496
}
@@ -501,7 +500,7 @@ public override IEnumerable<OverloadResult> Overloads {
501500
if (needNewSet) {
502501
var set = new AccumulatedOverloadResult(FunctionDefinition.Name, Documentation, names.Length);
503502
parameterSets.Add(set);
504-
set.TryAddOverload(null, null, names, vars, defaults, rtypes);
503+
set.TryAddOverload(null, null, names, vars, defaults, AnalysisSet.Create(rtypes));
505504
}
506505
}
507506

src/Analysis/Engine/Impl/Values/Protocols.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ protected override void EnsureMembers(IDictionary<string, IAnalysisSet> members)
187187

188188
private OverloadResult[] GenerateOverloads() {
189189
return new[] {
190-
new OverloadResult(Arguments.Select(ToParameterResult).ToArray(), Name, null, ReturnType.GetShortDescriptions())
190+
new OverloadResult(Arguments.Select(ToParameterResult).ToArray(), Name, null, ReturnType)
191191
};
192192
}
193193

0 commit comments

Comments
 (0)