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

Commit d81d776

Browse files
committed
added some comments and renamed some fields on PathResolver and Snapshot.
1 parent 8a5b808 commit d81d776

File tree

4 files changed

+110
-93
lines changed

4 files changed

+110
-93
lines changed

src/Analysis/Core/Impl/DependencyResolution/PathResolver.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
namespace Microsoft.Python.Analysis.Core.DependencyResolution {
2121
public sealed class PathResolver {
2222
public PathResolver(in PythonLanguageVersion pythonLanguageVersion, in string root, in ImmutableArray<string> interpreterSearchPaths, in ImmutableArray<string> userSearchPaths) {
23+
// need to audit whether CurrentSnapshot ever get updated concurrently
24+
// thread safety is probably fine but serialization is another issue where if 2 callers do TryAddModulePath or other calls concurrently,
25+
// they will use same CurrentSnapshot to update which ends up with 2 different snapshots with same version.
2326
CurrentSnapshot = new PathResolverSnapshot(pythonLanguageVersion, root, interpreterSearchPaths, userSearchPaths);
2427
}
2528

src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.Edge.cs

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,55 +35,69 @@ private readonly struct Edge {
3535
// ┌─╚═╗
3636
// [x] [y]
3737
//
38-
// will be stored as list of pairs: (2, a), (0, i), (1, y)
38+
// will be stored as list of pairs: (2, c), (0, i), (1, y)
3939
//
4040
// To provide immutability, it must be changed only by calling List<T>.Add
41-
private readonly ImmutableArray<(int index, Node node)> _vertices;
42-
private readonly int _index;
41+
private readonly ImmutableArray<(int nodeIndexInParent, Node node)> _pathFromRoot;
4342

44-
public Node Start => IsFirst ? default : _vertices[_index - 1].node;
45-
public int EndIndex => _vertices[_index].index;
46-
public Node End => _vertices[_index].node;
47-
public Edge Previous => IsFirst ? default : new Edge(_vertices, _index - 1);
48-
public Edge Next => IsLast ? default : new Edge(_vertices, _index + 1);
49-
public int PathLength => _vertices.Count;
50-
public bool IsFirst => _index == 0;
51-
public bool IsNonRooted => _vertices.Count > 0 && _vertices[0].node.Name == "*";
52-
public bool IsEmpty => _vertices.Count == 0;
53-
private bool IsLast => _index == _vertices.Count - 1;
43+
// indicates which entry in the _pathFromRoot correspond to this edge.
44+
private readonly int _indexInPath;
45+
46+
public Node ParentNode => IsFirst ? default : _pathFromRoot[_indexInPath - 1].node;
47+
public int NodeIndexInParent => _pathFromRoot[_indexInPath].nodeIndexInParent;
48+
public Node Node => _pathFromRoot[_indexInPath].node;
49+
public Edge Previous => IsFirst ? default : new Edge(_pathFromRoot, _indexInPath - 1);
50+
public Edge Next => IsLast ? default : new Edge(_pathFromRoot, _indexInPath + 1);
51+
public int PathLength => _pathFromRoot.Count;
52+
public bool IsFirst => _indexInPath == 0;
53+
public bool IsNonRooted => _pathFromRoot.Count > 0 && _pathFromRoot[0].node.Name == "*";
54+
public bool IsEmpty => _pathFromRoot.Count == 0;
55+
private bool IsLast => _indexInPath == _pathFromRoot.Count - 1;
5456

5557
public Edge(int startIndex, Node start) {
56-
_vertices = ImmutableArray<(int, Node)>.Empty.Add((startIndex, start));
57-
_index = 0;
58+
_pathFromRoot = ImmutableArray<(int, Node)>.Empty.Add((startIndex, start));
59+
_indexInPath = 0;
5860
}
5961

60-
public Edge FirstEdge => new Edge(_vertices, 0);
61-
public Edge GetPrevious(int count) => count > _index ? default : new Edge(_vertices, _index - count);
62-
public Edge GetNext(int count) => _index + count > _vertices.Count - 1 ? default : new Edge(_vertices, _index + count);
62+
public Edge FirstEdge => new Edge(_pathFromRoot, indexInVertices: 0);
63+
public Edge GetPrevious(int count) => count > _indexInPath ? default : new Edge(_pathFromRoot, _indexInPath - count);
64+
public Edge GetNext(int count) => _indexInPath + count > _pathFromRoot.Count - 1 ? default : new Edge(_pathFromRoot, _indexInPath + count);
65+
66+
private Edge(ImmutableArray<(int index, Node node)> vertices, int indexInVertices) {
67+
// Node has only down pointers for the immutable tree so that when tree needs to be updated
68+
// it can update only spine of the tree and reuse all other tree nodes. basically making
69+
// the tree incrementally updatable.
70+
// but not having Parent pointer makes using the tree data structure hard. so
71+
// Edge tracks the spine (provide Back/Parent pointer) but only created on demand for
72+
// a specific node requested.
73+
//
74+
// concept is similar to green-red tree.
75+
// see https://blog.yaakov.online/red-green-trees/
76+
// https://blogs.msdn.microsoft.com/ericlippert/2012/06/08/persistence-facades-and-roslyns-red-green-trees/
77+
// https://github.com/KirillOsenkov/Bliki/wiki/Roslyn-Immutable-Trees
6378

64-
private Edge(ImmutableArray<(int index, Node node)> vertices, int index) {
65-
_vertices = vertices;
66-
_index = index;
79+
_pathFromRoot = vertices;
80+
_indexInPath = indexInVertices;
6781
}
6882

6983
/// <summary>
7084
/// Appends new arc to the end vertex of current arc
7185
/// </summary>
72-
/// <param name="nextVertexIndex"></param>
86+
/// <param name="childVertexIndexToAppened"></param>
7387
/// <returns>New last arc</returns>
74-
public Edge Append(int nextVertexIndex) {
75-
var nextVertex = End.Children[nextVertexIndex];
76-
var trimLength = _vertices.Count - _index - 1;
77-
var vertices = _vertices.ReplaceAt(_index + 1, trimLength, (nextVertexIndex, nextVertex));
78-
return new Edge(vertices, _index + 1);
88+
public Edge Append(int childVertexIndexToAppened) {
89+
var nextVertex = Node.Children[childVertexIndexToAppened];
90+
var trimLength = _pathFromRoot.Count - _indexInPath - 1;
91+
var vertices = _pathFromRoot.ReplaceAt(_indexInPath + 1, trimLength, (childVertexIndexToAppened, nextVertex));
92+
return new Edge(vertices, _indexInPath + 1);
7993
}
8094

8195
public override bool Equals(object obj) => obj is Edge other && Equals(other);
82-
public bool Equals(Edge other) => Equals(_vertices, other._vertices) && _index == other._index;
96+
public bool Equals(Edge other) => Equals(_pathFromRoot, other._pathFromRoot) && _indexInPath == other._indexInPath;
8397

8498
public override int GetHashCode() {
8599
unchecked {
86-
return (_vertices.GetHashCode() * 397) ^ _index;
100+
return (_pathFromRoot.GetHashCode() * 397) ^ _indexInPath;
87101
}
88102
}
89103

@@ -92,9 +106,9 @@ public override int GetHashCode() {
92106

93107
private string DebuggerDisplay {
94108
get {
95-
var start = _index > 0 ? _vertices[_index - 1].node.Name : "null";
96-
var endIndex = _vertices[_index].index.ToString();
97-
var end = _vertices[_index].node.Name;
109+
var start = _indexInPath > 0 ? _pathFromRoot[_indexInPath - 1].node.Name : "null";
110+
var endIndex = _pathFromRoot[_indexInPath].nodeIndexInParent.ToString();
111+
var end = _pathFromRoot[_indexInPath].node.Name;
98112
return $"[{start}]-{endIndex}-[{end}]";
99113
}
100114
}

src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.Node.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public ImmutableArray<string> GetChildrenNames() {
110110
var results = ImmutableArray<string>.Empty;
111111

112112
foreach (var edge in _edges) {
113-
var children = edge.End.Children;
113+
var children = edge.Node.Children;
114114
foreach (var child in children) {
115115
if (IsNotInitPy(child)) {
116116
results = results.Add(child.Name);
@@ -123,7 +123,7 @@ public ImmutableArray<string> GetChildrenNames() {
123123

124124
public bool TryGetChildImport(string name, out IImportSearchResult child) {
125125
foreach (var edge in _edges) {
126-
var index = edge.End.GetChildIndex(name);
126+
var index = edge.Node.GetChildIndex(name);
127127
if (index == -1) {
128128
continue;
129129
}
@@ -132,7 +132,7 @@ public bool TryGetChildImport(string name, out IImportSearchResult child) {
132132
if (_snapshot.TryCreateModuleImport(childEdge, out var moduleImport)) {
133133
child = moduleImport;
134134
} else {
135-
child = new ImplicitPackageImport(new ChildrenSource(_snapshot, childEdge), childEdge.End.Name, childEdge.End.FullModuleName);
135+
child = new ImplicitPackageImport(new ChildrenSource(_snapshot, childEdge), childEdge.Node.Name, childEdge.Node.FullModuleName);
136136
}
137137

138138
return true;

0 commit comments

Comments
 (0)