Skip to content

Commit 4fec936

Browse files
committed
Fix microsoft#730: Go to reference is not working for a relative import
1 parent 19f8421 commit 4fec936

File tree

7 files changed

+190
-54
lines changed

7 files changed

+190
-54
lines changed

src/Analysis/Ast/Impl/Dependencies/DependencyResolver.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,28 @@ private static (ImmutableArray<WalkingVertex<TKey, TValue>>, int) ResolveLoops(I
181181
}
182182

183183
// Make all vertices from second pass loop have incoming edges from vertices from first pass loop and set unique loop numbers
184+
var outgoingVertices = new HashSet<WalkingVertex<TKey, TValue>>();
184185
foreach (var loop in secondPassLoops) {
186+
outgoingVertices.Clear();
185187
foreach (var secondPassVertex in loop) {
186188
var firstPassVertex = secondPassVertex.FirstPass;
187-
secondPassVertex.LoopNumber = loopsCount;
188189
firstPassVertex.AddOutgoing(loop);
189190

190-
// Copy outgoing edges to the second pass vertex
191191
foreach (var outgoingVertex in firstPassVertex.Outgoing) {
192-
if (outgoingVertex.LoopNumber == firstPassVertex.LoopNumber) {
192+
if (outgoingVertex.LoopNumber != firstPassVertex.LoopNumber) {
193+
// Collect outgoing vertices to reference them from loop
194+
outgoingVertices.Add(outgoingVertex);
195+
} else if (outgoingVertex.SecondPass != null) {
196+
// Copy outgoing edges to the second pass vertex
193197
secondPassVertex.AddOutgoing(outgoingVertex.SecondPass);
194198
}
195199
}
196200
}
197201

202+
foreach (var secondPassVertex in loop) {
203+
secondPassVertex.AddOutgoing(outgoingVertices);
204+
}
205+
198206
loopsCount++;
199207
}
200208

src/Analysis/Ast/Impl/Dependencies/WalkingVertex.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public WalkingVertex(DependencyVertex<TKey, TValue> vertex, WalkingVertex<TKey,
4343
DependencyVertex = vertex;
4444
FirstPass = firstPass;
4545
Index = -1;
46-
LoopNumber = -1;
46+
LoopNumber = firstPass?.LoopNumber ?? -1;
4747
_outgoing = new List<WalkingVertex<TKey, TValue>>();
4848
}
4949

@@ -63,6 +63,15 @@ public void AddOutgoing(List<WalkingVertex<TKey, TValue>> loop) {
6363
}
6464
}
6565

66+
public void AddOutgoing(HashSet<WalkingVertex<TKey, TValue>> loop) {
67+
CheckNotSealed();
68+
69+
_outgoing.AddRange(loop);
70+
foreach (var outgoingVertex in loop) {
71+
outgoingVertex.IncomingCount++;
72+
}
73+
}
74+
6675
public void RemoveOutgoingAt(int index) {
6776
CheckNotSealed();
6877

@@ -75,17 +84,6 @@ public WalkingVertex<TKey, TValue> CreateSecondPassVertex() {
7584
CheckNotSealed();
7685

7786
SecondPass = new WalkingVertex<TKey, TValue>(DependencyVertex, this);
78-
79-
for (var i = _outgoing.Count - 1; i >= 0; i--) {
80-
var outgoingVertex = _outgoing[i];
81-
if (LoopNumber == outgoingVertex.LoopNumber) {
82-
continue;
83-
}
84-
85-
SecondPass._outgoing.Add(outgoingVertex);
86-
_outgoing.RemoveAt(i);
87-
}
88-
8987
return SecondPass;
9088
}
9189

src/Analysis/Ast/Test/DependencyResolverTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,17 @@ public void TestInitialize()
3535
[TestCleanup]
3636
public void Cleanup() => TestEnvironmentImpl.TestCleanup();
3737

38-
// ReSharper disable StringLiteralTypo
38+
// ReSharper disable StringLiteralTypo
3939
[DataRow("A:BC|B:C|C", "CBA")]
4040
[DataRow("C|A:BC|B:C", "CBA")]
4141
[DataRow("C|B:AC|A:BC", "CBABA")]
42-
[DataRow("A:CE|B:A|C:B|D:B|E", "[BE]CAB[DC]A")]
42+
[DataRow("A:CE|B:A|C:B|D:B|E", "[BE]CABCAD")]
4343
[DataRow("A:D|B:DA|C:BA|D:AE|E", "[AE]DADBC")]
44-
[DataRow("A:C|C:B|B:A|D:AF|F:CE|E:BD", "ABCA[DB][EC]FDEF")]
44+
[DataRow("A:C|C:B|B:A|D:AF|F:CE|E:BD", "ABCABCDEFDEF")]
4545
[DataRow("A:BC|B:AC|C:BA|D:BC", "ACBACBD")]
4646
[DataRow("A|B|C|D:AB|E:BC", "[ABC][DE]")]
47-
[DataRow("A:CE|B:A|C:B|D:BC|E|F:C", "[BE]CABC[FDA]")]
47+
[DataRow("A:CE|B:A|C:B|D:BC|E|F:C", "[BE]CABCA[DF]")]
48+
[DataRow("A:D|B:E|C:F|D:E|E:F|F:D", "DFEDFE[ABC]")]
4849
// ReSharper restore StringLiteralTypo
4950
[DataTestMethod]
5051
public void NotifyChanges(string input, string output) {

src/Core/Impl/Collections/ImmutableArray.cs

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Collections.Generic;
1919
using System.Diagnostics.Contracts;
2020
using System.Runtime.CompilerServices;
21+
using System.Threading;
2122

2223
namespace Microsoft.Python.Core.Collections {
2324
/// <summary>
@@ -28,10 +29,13 @@ namespace Microsoft.Python.Core.Collections {
2829
/// <typeparam name="T"></typeparam>
2930
public struct ImmutableArray<T> : IReadOnlyList<T>, IEquatable<ImmutableArray<T>> {
3031
private readonly T[] _items;
32+
private readonly Ref _ref;
33+
private readonly int _count;
3134

3235
private ImmutableArray(T[] items, int count) {
3336
_items = items;
34-
Count = count;
37+
_ref = new Ref();
38+
_count = count;
3539
}
3640

3741
public static ImmutableArray<T> Empty { get; } = new ImmutableArray<T>(Array.Empty<T>(), 0);
@@ -67,26 +71,26 @@ public static ImmutableArray<T> Create<TKey>(Dictionary<TKey, T>.ValueCollection
6771
}
6872

6973
public T this[int index] => _items[index];
70-
public int Count { get; } // Length of the ImmutableArray.
74+
public int Count => _count; // Length of the ImmutableArray.
7175

7276
[Pure]
7377
public ImmutableArray<T> Add(T item) {
74-
var newCount = Count + 1;
78+
var newCount = _count + 1;
7579
var newItems = _items;
7680

77-
if (newCount > _items.Length) {
81+
if (newCount > _items.Length || Interlocked.CompareExchange(ref _ref.Count, newCount, _count) != _count) {
7882
var capacity = GetCapacity(newCount);
7983
newItems = new T[capacity];
80-
Array.Copy(_items, 0, newItems, 0, Count);
84+
Array.Copy(_items, 0, newItems, 0, _count);
8185
}
8286

83-
newItems[Count] = item;
87+
newItems[_count] = item;
8488
return new ImmutableArray<T>(newItems, newCount);
8589
}
8690

8791
[Pure]
8892
public ImmutableArray<T> AddRange(in ImmutableArray<T> items)
89-
=> AddRange(items._items, items.Count);
93+
=> AddRange(items._items, items._count);
9094

9195
[Pure]
9296
public ImmutableArray<T> AddRange(in T[] items)
@@ -98,16 +102,16 @@ private ImmutableArray<T> AddRange(in T[] items, int itemsCount) {
98102
return this;
99103
}
100104

101-
var newCount = Count + itemsCount;
105+
var newCount = _count + itemsCount;
102106
var newItems = _items;
103107

104-
if (newCount > _items.Length) {
108+
if (newCount > _items.Length || Interlocked.CompareExchange(ref _ref.Count, newCount, _count) != _count) {
105109
var capacity = GetCapacity(newCount);
106110
newItems = new T[capacity];
107-
Array.Copy(_items, 0, newItems, 0, Count);
111+
Array.Copy(_items, 0, newItems, 0, _count);
108112
}
109113

110-
Array.Copy(items, 0, newItems, Count, itemsCount);
114+
Array.Copy(items, 0, newItems, _count, itemsCount);
111115
return new ImmutableArray<T>(newItems, newCount);
112116
}
113117

@@ -119,7 +123,7 @@ public ImmutableArray<T> Remove(T value) {
119123

120124
[Pure]
121125
public ImmutableArray<T> RemoveAt(int index) {
122-
var newCount = Count - 1;
126+
var newCount = _count - 1;
123127

124128
var capacity = GetCapacity(newCount);
125129
var newArray = new T[capacity];
@@ -137,15 +141,15 @@ public ImmutableArray<T> RemoveAt(int index) {
137141

138142
[Pure]
139143
public ImmutableArray<T> InsertAt(int index, T value) {
140-
if (index > Count) {
144+
if (index > _count) {
141145
throw new IndexOutOfRangeException();
142146
}
143147

144-
if (index == Count) {
148+
if (index == _count) {
145149
return Add(value);
146150
}
147151

148-
var newCount = Count + 1;
152+
var newCount = _count + 1;
149153
var capacity = GetCapacity(newCount);
150154
var newArray = new T[capacity];
151155

@@ -154,7 +158,7 @@ public ImmutableArray<T> InsertAt(int index, T value) {
154158
}
155159

156160
newArray[index] = value;
157-
Array.Copy(_items, index, newArray, index + 1, Count - index);
161+
Array.Copy(_items, index, newArray, index + 1, _count - index);
158162

159163
return new ImmutableArray<T>(newArray, newCount);
160164
}
@@ -169,44 +173,45 @@ public ImmutableArray<T> ReplaceAt(int startIndex, int length, T value) {
169173
return ReplaceAt(startIndex, value);
170174
}
171175

172-
var newCount = Math.Max(Count - length + 1, startIndex + 1);
176+
var newCount = Math.Max(_count - length + 1, startIndex + 1);
173177
var capacity = GetCapacity(newCount);
174178
var newArray = new T[capacity];
175179

176180
if (startIndex > 0) {
177181
Array.Copy(_items, newArray, startIndex);
178182
}
179183

180-
newArray[startIndex + 1] = value;
184+
newArray[startIndex] = value;
181185

182-
if (startIndex + 2 < newCount) {
183-
Array.Copy(_items, startIndex + length + 1, newArray, startIndex + 1, newCount - startIndex - 2);
186+
var afterChangeIndex = startIndex + length;
187+
if (afterChangeIndex < _count) {
188+
Array.Copy(_items, afterChangeIndex, newArray, startIndex + 1, _count - afterChangeIndex);
184189
}
185190

186191
return new ImmutableArray<T>(newArray, newCount);
187192
}
188193

189194
[Pure]
190195
public ImmutableArray<T> ReplaceAt(int index, T value) {
191-
var capacity = GetCapacity(Count);
196+
var capacity = GetCapacity(_count);
192197
var newArray = new T[capacity];
193-
Array.Copy(_items, newArray, Count);
198+
Array.Copy(_items, newArray, _count);
194199
newArray[index] = value;
195-
return new ImmutableArray<T>(newArray, Count);
200+
return new ImmutableArray<T>(newArray, _count);
196201
}
197202

198203
[Pure]
199204
public ImmutableArray<T> Where(Func<T, bool> predicate) {
200205
var count = 0;
201-
for (var i = 0; i < Count; i++) {
206+
for (var i = 0; i < _count; i++) {
202207
if (predicate(_items[i])) {
203208
count++;
204209
}
205210
}
206211

207212
var index = 0;
208213
var items = new T[count];
209-
for (var i = 0; i < Count; i++) {
214+
for (var i = 0; i < _count; i++) {
210215
if (predicate(_items[i])) {
211216
items[index] = _items[i];
212217
index++;
@@ -218,15 +223,15 @@ public ImmutableArray<T> Where(Func<T, bool> predicate) {
218223

219224
[Pure]
220225
public ImmutableArray<TResult> Select<TResult>(Func<T, TResult> selector) {
221-
var items = new TResult[Count];
222-
for (var i = 0; i < Count; i++) {
226+
var items = new TResult[_count];
227+
for (var i = 0; i < _count; i++) {
223228
items[i] = selector(_items[i]);
224229
}
225230
return new ImmutableArray<TResult>(items, items.Length);
226231
}
227232

228233
[Pure]
229-
public int IndexOf(T value) => Array.IndexOf(_items, value, 0, Count);
234+
public int IndexOf(T value) => Array.IndexOf(_items, value, 0, _count);
230235

231236
[MethodImpl(MethodImplOptions.AggressiveInlining)]
232237
private int GetCapacity(int length) {
@@ -248,14 +253,14 @@ private int GetCapacity(int length) {
248253
}
249254

250255
public bool Equals(ImmutableArray<T> other)
251-
=> Equals(_items, other._items) && Count == other.Count;
256+
=> Equals(_items, other._items) && _count == other._count;
252257

253258
public override bool Equals(object obj) => obj is ImmutableArray<T> other && Equals(other);
254259

255260
public override int GetHashCode() {
256261
unchecked {
257262
var hashCode = (_items != null ? _items.GetHashCode() : 0);
258-
hashCode = (hashCode * 397) ^ Count;
263+
hashCode = (hashCode * 397) ^ _count;
259264
return hashCode;
260265
}
261266
}
@@ -292,13 +297,13 @@ public void Dispose() { }
292297
public bool MoveNext() {
293298
var localList = _owner;
294299

295-
if (_index < localList.Count) {
300+
if (_index < localList._count) {
296301
Current = localList._items[_index];
297302
_index++;
298303
return true;
299304
}
300305

301-
_index = _owner.Count + 1;
306+
_index = _owner._count + 1;
302307
Current = default;
303308
return false;
304309
}
@@ -312,5 +317,9 @@ void IEnumerator.Reset() {
312317
Current = default;
313318
}
314319
}
320+
321+
private class Ref {
322+
public int Count;
323+
}
315324
}
316325
}

0 commit comments

Comments
 (0)