Skip to content

Commit 6797fda

Browse files
committed
Add test case for Svelte language server and enhance VSIX package handling
1 parent 42864ca commit 6797fda

File tree

10 files changed

+927
-14
lines changed

10 files changed

+927
-14
lines changed

Directory.Packages.props

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@
5959
<PackageVersion Include="Photino.Blazor" Version="4.0.13" />
6060
<PackageVersion Include="R3" Version="1.3.0" />
6161
<PackageVersion Include="SharpDbg" Version="0.1.0-preview7" />
62+
<PackageVersion Include="StreamJsonRpc" Version="2.24.84" />
6263
<PackageVersion Include="TextMateSharp" Version="2.0.3" />
6364
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.0" />
6465
<PackageVersion Include="XtermBlazor" Version="2.2.0" />
66+
<PackageVersion Include="Nerdbank.Streams" Version="2.13.16" />
6567
</ItemGroup>
6668
<ItemGroup Label="Aspire">
6769
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.14.0" />
@@ -73,4 +75,4 @@
7375
<PackageVersion Include="Microsoft.CodeAnalysis.ExternalAccess.Razor.Features" Version="5.5.0-2.26120.116" />
7476
<PackageVersion Include="Microsoft.CodeAnalysis.Remote.ServiceHub" Version="5.5.0-2.26120.116" />
7577
</ItemGroup>
76-
</Project>
78+
</Project>

src/SharpIDE.Application.Tests/Features/LanguageExtensions/VsixPackageParserTests.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,68 @@ private static string CreateVsCodeVsixWithoutGrammar()
138138
return vsixPath;
139139
}
140140

141+
private static string CreateVisualStudioSvelteStyleVsix()
142+
{
143+
var tempDir = Directory.CreateTempSubdirectory("sharpide-svelte-vsix-test-");
144+
var vsixPath = Path.Combine(tempDir.FullName, "svelte.vsix");
145+
146+
using var archive = System.IO.Compression.ZipFile.Open(vsixPath, System.IO.Compression.ZipArchiveMode.Create);
147+
148+
var manifestEntry = archive.CreateEntry("extension.vsixmanifest");
149+
using (var writer = new StreamWriter(manifestEntry.Open()))
150+
{
151+
writer.Write(
152+
"""
153+
<?xml version="1.0" encoding="utf-8"?>
154+
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
155+
<Metadata>
156+
<Identity Language="en-US" Id="SvelteVisualStudio_2022.test" Version="2.2.0" Publisher="Jason Lyu" />
157+
<DisplayName>Svelte For Visual Studio</DisplayName>
158+
</Metadata>
159+
<Installation>
160+
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0, 18.0)" />
161+
</Installation>
162+
<Assets>
163+
<Asset Type="Microsoft.VisualStudio.VsPackage" Path="SvelteVisualStudio_2022.pkgdef" />
164+
</Assets>
165+
</PackageManifest>
166+
""");
167+
}
168+
169+
var pkgdefEntry = archive.CreateEntry("SvelteVisualStudio_2022.pkgdef");
170+
using (var writer = new StreamWriter(pkgdefEntry.Open()))
171+
{
172+
writer.Write(
173+
"""
174+
[$RootKey$\TextMate\Repositories]
175+
"svelte"="$PackageFolder$\Grammars"
176+
[$RootKey$\Editors\{91b34873-62ff-42e3-9664-a518b922478f}\Extensions]
177+
"svelte"=dword:00000064
178+
""");
179+
}
180+
181+
var grammarEntry = archive.CreateEntry("Grammars/svelte.tmLanguage.json");
182+
using (var writer = new StreamWriter(grammarEntry.Open()))
183+
{
184+
writer.Write(
185+
"""
186+
{
187+
"scopeName": "source.svelte",
188+
"fileTypes": ["svelte"],
189+
"patterns": []
190+
}
191+
""");
192+
}
193+
194+
var serverEntry = archive.CreateEntry("node_modules/svelte-language-server/bin/server.js");
195+
using (var writer = new StreamWriter(serverEntry.Open()))
196+
{
197+
writer.Write("console.log('svelte test server');");
198+
}
199+
200+
return vsixPath;
201+
}
202+
141203
// ── Metadata ────────────────────────────────────────────────────────────
142204

143205
[Fact]
@@ -290,4 +352,32 @@ public void Install_RejectsPackagesWithoutTextMateGrammars()
290352
.WithMessage("*does not contain any importable TextMate syntax files*");
291353
registry.GetAllExtensions().Should().BeEmpty();
292354
}
355+
356+
[Fact]
357+
public void Parse_VisualStudioSvelteStylePackage_FindsBundledNodeLanguageServer()
358+
{
359+
var vsixPath = CreateVisualStudioSvelteStyleVsix();
360+
361+
var result = VsixPackageParser.Parse(vsixPath);
362+
363+
result.PackageKind.Should().Be(ExtensionPackageKind.VisualStudio);
364+
result.Languages.Should().ContainSingle(l => l.FileExtensions.Contains(".svelte"));
365+
result.LanguageServers.Should().ContainSingle(s =>
366+
s.LanguageId == "svelte" &&
367+
s.Command == "node_modules/svelte-language-server/bin/server.js");
368+
result.LanguageServers[0].Args.Should().Equal("--stdio");
369+
}
370+
371+
[Fact]
372+
public void Install_VisualStudioSvelteStylePackage_ExtractsBundledLanguageServerAssets()
373+
{
374+
var vsixPath = CreateVisualStudioSvelteStyleVsix();
375+
var registry = new LanguageExtensionRegistry();
376+
var installer = new ExtensionInstaller(registry, NullLogger<ExtensionInstaller>.Instance);
377+
378+
var installed = installer.Install(vsixPath);
379+
380+
installed.LanguageServers.Should().ContainSingle();
381+
File.Exists(installed.LanguageServers[0].Command).Should().BeTrue();
382+
}
293383
}

src/SharpIDE.Application/DependencyInjection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public static IServiceCollection AddApplication(this IServiceCollection services
4646
services.AddScoped<DotnetTemplateService>();
4747
services.AddScoped<VsPersistenceSolutionService>();
4848
services.AddSingleton<LanguageExtensionRegistry>();
49+
services.AddSingleton<ImportedLanguageServerService>();
4950
services.AddScoped<ExtensionInstaller>();
5051
services.AddLogging();
5152
return services;

src/SharpIDE.Application/Features/LanguageExtensions/ExtensionInstaller.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ public InstalledExtension Install(string vsixPath)
8080
Command = Path.Combine(extractedPath, NormalizePath(s.Command)),
8181
Args = s.Args,
8282
WorkingDirectory = s.WorkingDirectory,
83-
TransportType = s.TransportType
83+
TransportType = s.TransportType,
84+
ConfigurationSections = s.ConfigurationSections,
85+
InitializationOptionsJson = s.InitializationOptionsJson
8486
})
8587
.ToList();
8688

@@ -148,6 +150,20 @@ private static void ExtractFiles(string vsixPath, string extractedPath, Installe
148150
{
149151
using var zip = ZipFile.OpenRead(vsixPath);
150152

153+
if (parsed.LanguageServers.Count > 0)
154+
{
155+
foreach (var entry in zip.Entries)
156+
{
157+
if (entry.FullName.EndsWith('/')) continue;
158+
159+
var destinationPath = Path.Combine(extractedPath, entry.FullName.Replace('/', Path.DirectorySeparatorChar));
160+
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)!);
161+
entry.ExtractToFile(destinationPath, overwrite: true);
162+
}
163+
164+
return;
165+
}
166+
151167
// Collect the set of paths to extract:
152168
// - All grammar assets declared in manifest
153169
// - All entries in LanguageServer/ directory

0 commit comments

Comments
 (0)