Skip to content

Commit dc8c541

Browse files
Migrate Node.js general options to Unified Settings
Register the three legacy general options with full bidirectional string migration, refresh unmodified cached values before launch, and add focused compatibility tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 7846f90 commit dc8c541

22 files changed

Lines changed: 946 additions & 12 deletions

‎Nodejs/Product/Nodejs/Nodejs.csproj‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@
312312
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
313313
<IncludeInVSIX>true</IncludeInVSIX>
314314
</Content>
315+
<Content Include="UnifiedSettings.pkgdef">
316+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
317+
<IncludeInVSIX>true</IncludeInVSIX>
318+
</Content>
319+
<Content Include="UnifiedSettings\NodejsGeneralOptions.registration.json">
320+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
321+
<IncludeInVSIX>true</IncludeInVSIX>
322+
</Content>
315323
<ZipItem Include="Templates\Files\JestUnitTest\UnitTest.js" />
316324
<ZipItem Include="Templates\Files\JestUnitTest\UnitTest.vstemplate" />
317325
<Content Include="Workspace\OpenFolderSchema.json">

‎Nodejs/Product/Nodejs/NodejsPackage.cs‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,36 @@
2424

2525
namespace Microsoft.NodejsTools
2626
{
27+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
28+
internal sealed class ProvideUnifiedSettingsOptionPageAttribute : RegistrationAttribute
29+
{
30+
private readonly string categoryName;
31+
private readonly string pageName;
32+
33+
public ProvideUnifiedSettingsOptionPageAttribute(string categoryName, string pageName)
34+
{
35+
this.categoryName = categoryName;
36+
this.pageName = pageName;
37+
}
38+
39+
public override void Register(RegistrationContext context)
40+
{
41+
using (var pageKey = context.CreateKey(
42+
string.Format(
43+
CultureInfo.InvariantCulture,
44+
@"ToolsOptionsPages\{0}\{1}",
45+
this.categoryName,
46+
this.pageName)))
47+
{
48+
pageKey.SetValue("IsInUnifiedSettings", 1);
49+
}
50+
}
51+
52+
public override void Unregister(RegistrationContext context)
53+
{
54+
}
55+
}
56+
2757
/// <summary>
2858
/// This is the class that implements the package exposed by this assembly.
2959
///
@@ -39,6 +69,7 @@ namespace Microsoft.NodejsTools
3969
[PackageRegistration(UseManagedResourcesOnly = true)]
4070
[Guid(Guids.NodejsPackageString)]
4171
[ProvideOptionPage(typeof(NodejsGeneralOptionsPage), "Node.js Tools", "General", 114, 115, true)]
72+
[ProvideUnifiedSettingsOptionPage("Node.js Tools", "General")]
4273
[WebSiteProject("JavaScript", "JavaScript")]
4374
[ProvideProjectFactory(typeof(NodejsProjectFactory), null, null, null, null, ".\\NullPath", LanguageVsTemplate = NodejsConstants.Nodejs, SortPriority = 0x17)] // outer flavor, no file extension
4475
[ProvideMenuResource("Menus.ctmenu", 1)] // This attribute is needed to let the shell know that this package exposes some menus.

‎Nodejs/Product/Nodejs/Options/NodejsGeneralOptionsPage.cs‎

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ public class NodejsGeneralOptionsPage : NodejsDialogPage
1414
private const string CheckForLongPathsSetting = "CheckForLongPaths";
1515

1616
private NodejsGeneralOptionsControl _window;
17+
private bool _waitOnAbnormalExit;
18+
private bool _waitOnNormalExit;
19+
private bool _editAndContinue;
20+
private bool _waitOnAbnormalExitModified;
21+
private bool _waitOnNormalExitModified;
22+
private bool _editAndContinueModified;
1723

1824
public NodejsGeneralOptionsPage()
1925
: base("General")
@@ -38,18 +44,42 @@ protected override IWin32Window Window
3844
/// True if Node processes should pause for input before exiting
3945
/// if they exit abnormally.
4046
/// </summary>
41-
public bool WaitOnAbnormalExit { get; set; }
47+
public bool WaitOnAbnormalExit
48+
{
49+
get => this._waitOnAbnormalExit;
50+
set
51+
{
52+
this._waitOnAbnormalExit = value;
53+
this._waitOnAbnormalExitModified = true;
54+
}
55+
}
4256

4357
/// <summary>
4458
/// True if Node processes should pause for input before exiting
4559
/// if they exit normally.
4660
/// </summary>
47-
public bool WaitOnNormalExit { get; set; }
61+
public bool WaitOnNormalExit
62+
{
63+
get => this._waitOnNormalExit;
64+
set
65+
{
66+
this._waitOnNormalExit = value;
67+
this._waitOnNormalExitModified = true;
68+
}
69+
}
4870

4971
/// <summary>
5072
/// Indicates whether Edit and Continue feature should be enabled.
5173
/// </summary>
52-
public bool EditAndContinue { get; set; }
74+
public bool EditAndContinue
75+
{
76+
get => this._editAndContinue;
77+
set
78+
{
79+
this._editAndContinue = value;
80+
this._editAndContinueModified = true;
81+
}
82+
}
5383

5484
/// <summary>
5585
/// Resets settings back to their defaults. This should be followed by
@@ -65,12 +95,36 @@ public override void ResetSettings()
6595

6696
public override void LoadSettingsFromStorage()
6797
{
68-
// Load settings from storage.
69-
this.WaitOnAbnormalExit = LoadBool(WaitOnAbnormalExitSetting) ?? true;
70-
this.WaitOnNormalExit = LoadBool(WaitOnNormalExitSetting) ?? false;
71-
this.EditAndContinue = LoadBool(EditAndContinueSetting) ?? true;
98+
this._waitOnAbnormalExit = LoadBool(WaitOnAbnormalExitSetting) ?? true;
99+
this._waitOnNormalExit = LoadBool(WaitOnNormalExitSetting) ?? false;
100+
this._editAndContinue = LoadBool(EditAndContinueSetting) ?? true;
101+
this._waitOnAbnormalExitModified = false;
102+
this._waitOnNormalExitModified = false;
103+
this._editAndContinueModified = false;
104+
105+
if (this._window != null)
106+
{
107+
this._window.SyncControlWithPageSettings(this);
108+
}
109+
}
110+
111+
internal void RefreshSettingsFromStorage()
112+
{
113+
if (!this._waitOnAbnormalExitModified)
114+
{
115+
this._waitOnAbnormalExit = LoadBool(WaitOnAbnormalExitSetting) ?? true;
116+
}
117+
118+
if (!this._waitOnNormalExitModified)
119+
{
120+
this._waitOnNormalExit = LoadBool(WaitOnNormalExitSetting) ?? false;
121+
}
122+
123+
if (!this._editAndContinueModified)
124+
{
125+
this._editAndContinue = LoadBool(EditAndContinueSetting) ?? true;
126+
}
72127

73-
// Synchronize UI with backing properties.
74128
if (this._window != null)
75129
{
76130
this._window.SyncControlWithPageSettings(this);
@@ -79,16 +133,17 @@ public override void LoadSettingsFromStorage()
79133

80134
public override void SaveSettingsToStorage()
81135
{
82-
// Synchronize backing properties with UI.
83136
if (this._window != null)
84137
{
85138
this._window.SyncPageWithControlSettings(this);
86139
}
87140

88-
// Save settings.
89141
SaveBool(WaitOnNormalExitSetting, this.WaitOnNormalExit);
90142
SaveBool(WaitOnAbnormalExitSetting, this.WaitOnAbnormalExit);
91143
SaveBool(EditAndContinueSetting, this.EditAndContinue);
144+
this._waitOnAbnormalExitModified = false;
145+
this._waitOnNormalExitModified = false;
146+
this._editAndContinueModified = false;
92147
}
93148
}
94149
}

‎Nodejs/Product/Nodejs/Project/NodejsProjectLauncher.cs‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,13 @@ private void StartNodeProcess(string file, string nodePath, bool shouldStartBrow
136136
psi.EnvironmentVariables[nameValue.Key] = nameValue.Value;
137137
}
138138

139+
var generalOptions = NodejsPackage.Instance.GeneralOptionsPage;
140+
generalOptions.RefreshSettingsFromStorage();
141+
139142
var process = NodeProcess.Start(
140143
psi,
141-
waitOnAbnormal: NodejsPackage.Instance.GeneralOptionsPage.WaitOnAbnormalExit,
142-
waitOnNormal: NodejsPackage.Instance.GeneralOptionsPage.WaitOnNormalExit);
144+
waitOnAbnormal: generalOptions.WaitOnAbnormalExit,
145+
waitOnNormal: generalOptions.WaitOnNormalExit);
143146

144147
this._project.OnDispose += process.ResponseToTerminateEvent;
145148

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// CacheTag must change whenever the Unified Settings manifest changes.
2+
[$RootKey$\SettingsManifests\{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}]
3+
@="Microsoft.NodejsTools.NodejsPackage"
4+
"ManifestPath"="$PackageFolder$\UnifiedSettings\NodejsGeneralOptions.registration.json"
5+
"CacheTag"=qword:01DD3FA6EA131C30
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"$schema": "https://aka.ms/unified-settings-experience/registration/schema",
3+
"properties": {
4+
"debugging.nodejs.general.waitOnAbnormalExit": {
5+
"type": "boolean",
6+
"title": "@UnifiedSettings_WaitOnAbnormalExit;{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}",
7+
"default": true,
8+
"order": 0,
9+
"migration": {
10+
"custom": {
11+
"mode": "full",
12+
"inputs": [
13+
{
14+
"store": "VsUserSettingsRegistry",
15+
"path": "NodejsTools\\Options\\General\\WaitOnAbnormalExit"
16+
}
17+
],
18+
"map": [
19+
{
20+
"result": true,
21+
"matches": [ "True" ]
22+
},
23+
{
24+
"result": false,
25+
"matches": [ "False" ]
26+
}
27+
]
28+
}
29+
}
30+
},
31+
"debugging.nodejs.general.waitOnNormalExit": {
32+
"type": "boolean",
33+
"title": "@UnifiedSettings_WaitOnNormalExit;{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}",
34+
"default": false,
35+
"order": 1,
36+
"migration": {
37+
"custom": {
38+
"mode": "full",
39+
"inputs": [
40+
{
41+
"store": "VsUserSettingsRegistry",
42+
"path": "NodejsTools\\Options\\General\\WaitOnNormalExit"
43+
}
44+
],
45+
"map": [
46+
{
47+
"result": true,
48+
"matches": [ "True" ]
49+
},
50+
{
51+
"result": false,
52+
"matches": [ "False" ]
53+
}
54+
]
55+
}
56+
}
57+
},
58+
"debugging.nodejs.general.editAndContinue": {
59+
"type": "boolean",
60+
"title": "@UnifiedSettings_EditAndContinue;{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}",
61+
"default": true,
62+
"order": 2,
63+
"migration": {
64+
"custom": {
65+
"mode": "full",
66+
"inputs": [
67+
{
68+
"store": "VsUserSettingsRegistry",
69+
"path": "NodejsTools\\Options\\General\\EditAndContinue"
70+
}
71+
],
72+
"map": [
73+
{
74+
"result": true,
75+
"matches": [ "True" ]
76+
},
77+
{
78+
"result": false,
79+
"matches": [ "False" ]
80+
}
81+
]
82+
}
83+
}
84+
}
85+
},
86+
"categories": {
87+
"debugging.nodejs": {
88+
"title": "@114;{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}"
89+
},
90+
"debugging.nodejs.general": {
91+
"title": "@115;{FE8A8C3D-328A-476D-99F9-2A24B75F8C7F}",
92+
"legacyOptionPageId": "EF677A38-0953-39C2-A228-2FBE8F8F082E"
93+
}
94+
}
95+
}

‎Nodejs/Product/Nodejs/VSPackage.resx‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@
138138
<data name="115" xml:space="preserve">
139139
<value>General</value>
140140
</data>
141+
<data name="UnifiedSettings_WaitOnAbnormalExit" xml:space="preserve">
142+
<value>Wait for input when process exits abnormally</value>
143+
</data>
144+
<data name="UnifiedSettings_WaitOnNormalExit" xml:space="preserve">
145+
<value>Wait for input when process exits normally</value>
146+
</data>
147+
<data name="UnifiedSettings_EditAndContinue" xml:space="preserve">
148+
<value>Enable Edit and Continue</value>
149+
</data>
141150
<data name="116" xml:space="preserve">
142151
<value>Npm</value>
143152
</data>

0 commit comments

Comments
 (0)