Skip to content

Commit cab3ad8

Browse files
authored
Merge pull request #1918 from paulvanbrenk/fileWatcherUpdate
File watcher update
2 parents de36a3c + 87809d3 commit cab3ad8

13 files changed

+297
-246
lines changed

Build/xTVS.ruleset

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22
<RuleSet Name="xTVS Coding Rules" Description="xTVS ruleset with low-value tests disabled." ToolsVersion="10.0">
33
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
44
<Rule Id="CA2204" Action="None" />
5-
<Rule Id="CA2210" Action="None" /> <!-- mt.exe problem with signing -->
6-
5+
<Rule Id="CA2210" Action="None" />
6+
<!-- mt.exe problem with signing -->
77
<Rule Id="CA1001" Action="Warning" />
88
<Rule Id="CA1009" Action="Warning" />
99
<Rule Id="CA1016" Action="Warning" />
1010
<Rule Id="CA1049" Action="Warning" />
11-
<Rule Id="CA1033" Action="None" /> <!-- Explicit interface implementation on base classes -->
11+
<Rule Id="CA1033" Action="None" />
12+
<!-- Explicit interface implementation on base classes -->
1213
<Rule Id="CA1060" Action="Warning" />
1314
<Rule Id="CA1061" Action="Warning" />
1415
<Rule Id="CA1063" Action="Warning" />
15-
<Rule Id="CA1065" Action="None" /> <!-- Throw from property accessors -->
16+
<Rule Id="CA1065" Action="None" />
17+
<!-- Throw from property accessors -->
1618
<Rule Id="CA1301" Action="Warning" />
1719
<Rule Id="CA1400" Action="Warning" />
1820
<Rule Id="CA1401" Action="Warning" />
@@ -49,7 +51,8 @@
4951
<Rule Id="CA2147" Action="Warning" />
5052
<Rule Id="CA2149" Action="Warning" />
5153
<Rule Id="CA2200" Action="Warning" />
52-
<Rule Id="CA2202" Action="None" /> <!-- Do not dispose objects multiple times -->
54+
<Rule Id="CA2202" Action="None" />
55+
<!-- Do not dispose objects multiple times -->
5356
<Rule Id="CA2207" Action="Warning" />
5457
<Rule Id="CA2212" Action="Warning" />
5558
<Rule Id="CA2213" Action="Warning" />
@@ -66,21 +69,27 @@
6669
<Rule Id="CA2240" Action="Warning" />
6770
<Rule Id="CA2241" Action="Warning" />
6871
<Rule Id="CA2242" Action="Warning" />
69-
70-
<Rule Id="CA1008" Action="None" /> <!-- Enum should have zero value -->
72+
<Rule Id="CA1008" Action="None" />
73+
<!-- Enum should have zero value -->
7174
<Rule Id="CA1013" Action="Warning" />
72-
<Rule Id="CA1303" Action="None" /> <!-- Do not pass literals as localized parameters -->
73-
<Rule Id="CA1308" Action="None" /> <!-- Normalize strings to uppercase -->
74-
<Rule Id="CA1806" Action="None" /> <!-- Do not ignore method results -->
75+
<Rule Id="CA1303" Action="None" />
76+
<!-- Do not pass literals as localized parameters -->
77+
<Rule Id="CA1308" Action="None" />
78+
<!-- Normalize strings to uppercase -->
79+
<Rule Id="CA1806" Action="None" />
80+
<!-- Do not ignore method results -->
7581
<Rule Id="CA1816" Action="Warning" />
7682
<Rule Id="CA1819" Action="Warning" />
7783
<Rule Id="CA1820" Action="Warning" />
7884
<Rule Id="CA1903" Action="Warning" />
79-
<Rule Id="CA2004" Action="None" /> <!-- Remove calls to GC.KeepAlive -->
85+
<Rule Id="CA2004" Action="None" />
86+
<!-- Remove calls to GC.KeepAlive -->
8087
<Rule Id="CA2006" Action="Warning" />
8188
<Rule Id="CA2102" Action="Warning" />
82-
<Rule Id="CA2104" Action="None" /> <!-- Do not declare readonly mutable types -->
83-
<Rule Id="CA2105" Action="None" /> <!-- Array fields should not be read only -->
89+
<Rule Id="CA2104" Action="None" />
90+
<!-- Do not declare readonly mutable types -->
91+
<Rule Id="CA2105" Action="None" />
92+
<!-- Array fields should not be read only -->
8493
<Rule Id="CA2106" Action="Warning" />
8594
<Rule Id="CA2115" Action="Warning" />
8695
<Rule Id="CA2119" Action="Warning" />
@@ -90,11 +99,30 @@
9099
<Rule Id="CA2205" Action="Warning" />
91100
<Rule Id="CA2215" Action="Warning" />
92101
<Rule Id="CA2221" Action="Warning" />
93-
<Rule Id="CA2222" Action="None" /> <!-- Do not decrease inherited member visibility -->
102+
<Rule Id="CA2222" Action="None" />
103+
<!-- Do not decrease inherited member visibility -->
94104
<Rule Id="CA2223" Action="Warning" />
95105
<Rule Id="CA2224" Action="Warning" />
96106
<Rule Id="CA2226" Action="Warning" />
97107
<Rule Id="CA2227" Action="Warning" />
98108
<Rule Id="CA2239" Action="Warning" />
99109
</Rules>
100-
</RuleSet>
110+
<Rules AnalyzerId="Microsoft.VisualStudio.Threading.Analyzers" RuleNamespace="Microsoft.VisualStudio.Threading.Analyzers">
111+
<Rule Id="VSTHRD001" Action="Info" />
112+
<Rule Id="VSTHRD002" Action="Info" />
113+
<Rule Id="VSTHRD003" Action="Info" />
114+
<Rule Id="VSTHRD010" Action="Info" />
115+
<Rule Id="VSTHRD011" Action="Info" />
116+
<Rule Id="VSTHRD012" Action="Info" />
117+
<Rule Id="VSTHRD100" Action="Info" />
118+
<Rule Id="VSTHRD101" Action="Info" />
119+
<Rule Id="VSTHRD102" Action="Info" />
120+
<Rule Id="VSTHRD103" Action="Info" />
121+
<Rule Id="VSTHRD104" Action="Info" />
122+
<Rule Id="VSTHRD105" Action="Info" />
123+
<Rule Id="VSTHRD106" Action="Info" />
124+
<Rule Id="VSTHRD107" Action="Info" />
125+
<Rule Id="VSTHRD108" Action="Info" />
126+
<Rule Id="VSTHRD200" Action="Info" />
127+
</Rules>
128+
</RuleSet>

Nodejs/Product/Nodejs/Nodejs.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,9 @@
12081208
<PackageReference Include="Microsoft.VisualStudio.AppDesigner">
12091209
<Version>15.3.0-rc-6162104</Version>
12101210
</PackageReference>
1211+
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.15.7.DesignTime">
1212+
<Version>15.7.1</Version>
1213+
</PackageReference>
12111214
<PackageReference Include="Microsoft.VisualStudio.Telemetry">
12121215
<Version>15.7.942-master669188BE</Version>
12131216
</PackageReference>

Nodejs/Product/Nodejs/SharedProject/AssemblyReferenceNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ protected virtual void OnAssemblyReferenceChangedOnDisk(object sender, FileChang
400400
}
401401

402402
// We only care about file deletes, so check for one before enumerating references.
403-
if ((e.FileChangeFlag & _VSFILECHANGEFLAGS.VSFILECHG_Del) == 0)
403+
if (e.FileChange != WatcherChangeTypes.Deleted)
404404
{
405405
return;
406406
}

Nodejs/Product/Nodejs/SharedProject/CommonProjectNode.FileSystemChange.cs

Lines changed: 94 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,19 @@ internal abstract partial class CommonProjectNode
1414
/// Represents an individual change to the file system. We process these in bulk on the
1515
/// UI thread.
1616
/// </summary>
17-
[DebuggerDisplay("FileSystemChange: {isRename} {Type} {path}")]
17+
[DebuggerDisplay("FileSystemChange: {Type} {path}")]
1818
private sealed class FileSystemChange
1919
{
2020
private readonly CommonProjectNode project;
2121
private readonly string path;
22-
private readonly bool isRename;
2322

2423
public readonly WatcherChangeTypes Type;
2524

26-
public FileSystemChange(CommonProjectNode project, WatcherChangeTypes changeType, string path, bool isRename = false)
25+
public FileSystemChange(CommonProjectNode project, WatcherChangeTypes changeType, string path)
2726
{
2827
this.project = project;
2928
this.Type = changeType;
3029
this.path = path;
31-
this.isRename = isRename;
3230
}
3331

3432
private void RedrawIcon(HierarchyNode node)
@@ -50,12 +48,26 @@ public async Task ProcessChangeAsync()
5048
{
5149
child = this.project.FindNodeByFullPath(this.path + Path.DirectorySeparatorChar);
5250
}
51+
5352
switch (this.Type)
5453
{
5554
case WatcherChangeTypes.Deleted:
56-
ChildDeleted(child);
55+
if (child != null)
56+
{
57+
ChildDeleted(child);
58+
}
5759
break;
5860
case WatcherChangeTypes.Created:
61+
if (child != null)
62+
{
63+
// this child already exists redraw the icon
64+
this.project.ReDrawNode(child, UIHierarchyElement.Icon);
65+
}
66+
else
67+
{
68+
await ChildCreatedAsync(child);
69+
}
70+
break;
5971
case WatcherChangeTypes.Changed:
6072
// we only care about the attributes
6173
if (this.project.IsFileHidden(this.path))
@@ -68,9 +80,11 @@ public async Task ProcessChangeAsync()
6880
}
6981
else
7082
{
71-
// either a new or attributes have changed
72-
// add the file
73-
await ChildCreatedAsync(child);
83+
if (child == null)
84+
{
85+
// attributes must of changed from hidden, add the file
86+
await ChildCreatedAsync(null);
87+
}
7488
}
7589
break;
7690
}
@@ -96,110 +110,104 @@ private void RemoveAllFilesChildren(HierarchyNode parent)
96110

97111
private void ChildDeleted(HierarchyNode child)
98112
{
99-
if (child != null)
113+
if (child == null)
100114
{
101-
this.project.TryDeactivateSymLinkWatcher(child);
115+
throw new InvalidOperationException("Deleted, but child is null.");
116+
}
102117

103-
// rapid changes can arrive out of order, if the file or directory
104-
// actually exists ignore the event.
105-
if ((!File.Exists(child.Url) && !Directory.Exists(child.Url)) ||
106-
this.project.IsFileHidden(child.Url))
118+
this.project.TryDeactivateSymLinkWatcher(child);
119+
120+
// rapid changes can arrive out of order, if the file or directory
121+
// actually exists ignore the event.
122+
if ((!File.Exists(child.Url) && !Directory.Exists(child.Url)) ||
123+
this.project.IsFileHidden(child.Url))
124+
{
125+
if (child.ItemNode == null)
107126
{
108-
if (child.ItemNode == null)
109-
{
110-
// nodes should all have ItemNodes, the project is special.
111-
Debug.Assert(child is ProjectNode);
112-
return;
113-
}
127+
// nodes should all have ItemNodes, the project is special.
128+
Debug.Assert(child is ProjectNode);
129+
return;
130+
}
114131

115-
if (child.ItemNode.IsExcluded)
116-
{
117-
this.RemoveAllFilesChildren(child);
118-
// deleting a show all files item, remove the node.
119-
this.project.OnItemDeleted(child);
120-
child.Parent.RemoveChild(child);
121-
child.Close();
122-
}
123-
else
124-
{
125-
Debug.Assert(!child.IsNonMemberItem);
126-
// deleting an item in the project, fix the icon, also
127-
// fix the icon of all children which we may have not
128-
// received delete notifications for
129-
this.RedrawIcon(child);
130-
}
132+
if (child.ItemNode.IsExcluded)
133+
{
134+
this.RemoveAllFilesChildren(child);
135+
// deleting a show all files item, remove the node.
136+
this.project.OnItemDeleted(child);
137+
child.Parent.RemoveChild(child);
138+
child.Close();
139+
}
140+
else
141+
{
142+
Debug.Assert(!child.IsNonMemberItem);
143+
// deleting an item in the project, fix the icon, also
144+
// fix the icon of all children which we may have not
145+
// received delete notifications for
146+
this.RedrawIcon(child);
131147
}
132148
}
133149
}
134150

135151
private async Task ChildCreatedAsync(HierarchyNode child)
136152
{
137-
if (child != null)
153+
if (this.project.IsFileHidden(this.path))
138154
{
139-
// creating an item which was in the project, fix the icon.
140-
this.project.ReDrawNode(child, UIHierarchyElement.Icon);
155+
// don't add hidden files/folders
156+
return;
141157
}
142-
else
143-
{
144-
if (this.project.IsFileHidden(this.path))
145-
{
146-
// don't add hidden files/folders
147-
return;
148-
}
149158

150-
// creating a new item, need to create the on all files node
151-
var parent = this.project.GetParentFolderForPath(this.path);
159+
// creating a new item, need to create the on all files node
160+
var parent = this.project.GetParentFolderForPath(this.path);
152161

153-
if (parent == null)
154-
{
155-
// we've hit an error while adding too many files, the file system watcher
156-
// couldn't keep up. That's alright, we'll merge the files in correctly
157-
// in a little while...
158-
return;
159-
}
162+
if (parent == null)
163+
{
164+
// we've hit an error while adding too many files, the file system watcher
165+
// couldn't keep up. That's alright, we'll merge the files in correctly
166+
// in a little while...
167+
return;
168+
}
160169

161-
var wasExpanded = parent.GetIsExpanded();
170+
var wasExpanded = parent.GetIsExpanded();
162171

163-
if (Directory.Exists(this.path))
172+
if (Directory.Exists(this.path))
173+
{
174+
if (IsFileSymLink(this.path))
164175
{
165-
if (IsFileSymLink(this.path))
176+
var parentDir = CommonUtils.GetParent(this.path);
177+
if (IsRecursiveSymLink(parentDir, this.path))
166178
{
167-
var parentDir = CommonUtils.GetParent(this.path);
168-
if (IsRecursiveSymLink(parentDir, this.path))
169-
{
170-
// don't add recusrive sym link directory
171-
return;
172-
}
173-
174-
// otherwise we're going to need a new file system watcher
175-
this.project.CreateSymLinkWatcher(this.path);
179+
// don't add recusrive sym link directory
180+
return;
176181
}
177182

178-
var folderNode = this.project.AddAllFilesFolder(parent, this.path + Path.DirectorySeparatorChar);
179-
var folderNodeWasExpanded = folderNode.GetIsExpanded();
183+
// otherwise we're going to need a new file system watcher
184+
this.project.CreateSymLinkWatcher(this.path);
185+
}
180186

181-
// then add the folder nodes
182-
await this.project.MergeDiskNodesAsync(folderNode, this.path).ConfigureAwait(true);
187+
var folderNode = this.project.AddAllFilesFolder(parent, this.path + Path.DirectorySeparatorChar);
188+
var folderNodeWasExpanded = folderNode.GetIsExpanded();
183189

184-
// Assert we're back on the UI thread
185-
this.project.Site.GetUIThread().MustBeCalledFromUIThread();
186-
187-
this.project.OnInvalidateItems(folderNode);
190+
// then add the folder nodes
191+
await this.project.MergeDiskNodesAsync(folderNode, this.path).ConfigureAwait(true);
188192

189-
folderNode.ExpandItem(folderNodeWasExpanded ? EXPANDFLAGS.EXPF_ExpandFolder : EXPANDFLAGS.EXPF_CollapseFolder);
190-
}
191-
else if (File.Exists(this.path))
193+
// Assert we're back on the UI thread
194+
this.project.Site.GetUIThread().MustBeCalledFromUIThread();
195+
196+
this.project.OnInvalidateItems(folderNode);
197+
198+
folderNode.ExpandItem(folderNodeWasExpanded ? EXPANDFLAGS.EXPF_ExpandFolder : EXPANDFLAGS.EXPF_CollapseFolder);
199+
}
200+
else if (File.Exists(this.path))
201+
{
202+
// rapid changes can arrive out of order, make sure the file still exists
203+
this.project.AddAllFilesFile(parent, this.path);
204+
if (StringComparer.OrdinalIgnoreCase.Equals(this.project.GetStartupFile(), this.path))
192205
{
193-
// rapid changes can arrive out of order, make sure the file still exists
194-
this.project.AddAllFilesFile(parent, this.path);
195-
if (StringComparer.OrdinalIgnoreCase.Equals(this.project.GetStartupFile(), this.path))
196-
{
197-
this.project.BoldStartupItem();
198-
}
206+
this.project.BoldStartupItem();
199207
}
200-
201-
parent.ExpandItem(wasExpanded ? EXPANDFLAGS.EXPF_ExpandFolder : EXPANDFLAGS.EXPF_CollapseFolder);
202208
}
209+
210+
parent.ExpandItem(wasExpanded ? EXPANDFLAGS.EXPF_ExpandFolder : EXPANDFLAGS.EXPF_CollapseFolder);
203211
}
204212
}
205213
}

0 commit comments

Comments
 (0)