-
Notifications
You must be signed in to change notification settings - Fork 392
/
Copy pathDynamicItemHandler.cs
110 lines (90 loc) · 4.21 KB
/
DynamicItemHandler.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.IO;
using Microsoft.VisualStudio.ProjectSystem.Logging;
namespace Microsoft.VisualStudio.ProjectSystem.LanguageServices.Handlers
{
/// <summary>
/// Handles changes to dynamic items, such as Razor CSHTML files.
/// </summary>
[Export(typeof(IWorkspaceContextHandler))]
internal class DynamicItemHandler : AbstractWorkspaceContextHandler, IProjectEvaluationHandler
{
private const string DynamicFileExtension = ".cshtml";
private readonly UnconfiguredProject _project;
private readonly HashSet<string> _paths = new HashSet<string>(StringComparers.Paths);
[ImportingConstructor]
public DynamicItemHandler(UnconfiguredProject project)
{
_project = project;
}
public string ProjectEvaluationRule
{
get { return Content.SchemaName; }
}
public void Handle(IComparable version, IProjectChangeDescription projectChange, bool isActiveContext, IProjectLogger logger)
{
Requires.NotNull(version, nameof(version));
Requires.NotNull(projectChange, nameof(projectChange));
Requires.NotNull(logger, nameof(logger));
VerifyInitialized();
IProjectChangeDiff difference = HandlerServices.NormalizeRenames(projectChange.Difference);
foreach (string includePath in difference.RemovedItems)
{
if (IsDynamicFile(includePath))
{
RemoveFromContextIfPresent(includePath, logger);
}
}
foreach (string includePath in difference.AddedItems)
{
if (IsDynamicFile(includePath))
{
IImmutableDictionary<string, string> metadata = projectChange.After.Items.GetValueOrDefault(includePath, ImmutableStringDictionary<string>.EmptyOrdinal);
AddToContextIfNotPresent(includePath, metadata, logger);
}
}
// We Remove then Add changed items to pick up the Linked metadata
foreach (string includePath in difference.ChangedItems)
{
if (IsDynamicFile(includePath))
{
IImmutableDictionary<string, string> metadata = projectChange.After.Items.GetValueOrDefault(includePath, ImmutableStringDictionary<string>.EmptyOrdinal);
RemoveFromContextIfPresent(includePath, logger);
AddToContextIfNotPresent(includePath, metadata, logger);
}
}
}
private void AddToContextIfNotPresent(string includePath, IImmutableDictionary<string, string> metadata, IProjectLogger logger)
{
string fullPath = _project.MakeRooted(includePath);
if (!_paths.Contains(fullPath))
{
string[] folderNames = FileItemServices.GetLogicalFolderNames(Path.GetDirectoryName(_project.FullPath), fullPath, metadata);
logger.WriteLine("Adding dynamic file '{0}'", fullPath);
Context.AddDynamicFile(fullPath, folderNames);
bool added = _paths.Add(fullPath);
Assumes.True(added);
}
}
private void RemoveFromContextIfPresent(string includePath, IProjectLogger logger)
{
string fullPath = _project.MakeRooted(includePath);
if (_paths.Contains(fullPath))
{
logger.WriteLine("Removing dynamic file '{0}'", fullPath);
Context.RemoveDynamicFile(fullPath);
bool removed = _paths.Remove(fullPath);
Assumes.True(removed);
}
}
private static bool IsDynamicFile(string includePath)
{
// Note a file called just '.cshtml' is still considered a Razor file
return includePath.EndsWith(DynamicFileExtension, StringComparison.OrdinalIgnoreCase);
}
}
}