From 87431db76b0fe609e170c6f57fad3651f2ddf285 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Tue, 29 Apr 2025 21:14:12 +0200 Subject: [PATCH 1/2] Update SourceBrowser --- global.json | 2 +- src/SourceBrowser.hash | 2 +- src/SourceBrowser/.gitignore | 3 ++ src/SourceBrowser/TestCode/Project2/Class1.cs | 16 ++++++- .../src/BinLogParser/BinLogParser.csproj | 2 +- .../src/BinLogToSln/BinLogToSln.csproj | 2 +- src/SourceBrowser/src/Common/Common.csproj | 2 +- src/SourceBrowser/src/Common/PriorityQueue.cs | 8 +++- .../src/Directory.Packages.props | 48 +++++++++---------- .../src/HtmlGenerator/CommandLineOptions.cs | 15 +++++- .../Pass1-Generation/Classifier.cs | 3 +- .../DocumentGenerator.Links.cs | 3 +- .../Pass1-Generation/DocumentGenerator.cs | 14 +++--- .../Pass1-Generation/MetadataAsSource.cs | 4 +- .../Pass1-Generation/ProjectGenerator.cs | 36 +++++++++++--- .../Pass1-Generation/SolutionGenerator.cs | 6 ++- .../src/HtmlGenerator/Program.cs | 10 ++-- .../src/HtmlGenerator/SourceBrowser.nuspec | 2 + .../src/HtmlGenerator/Utilities/Paths.cs | 2 +- .../HtmlGenerator/Utilities/WorkspaceHacks.cs | 14 +++--- .../src/HtmlGenerator/app.config | 19 ++++++++ .../SourceIndexServer.Tests.csproj | 2 +- .../Controllers/OpenSearchController.cs | 26 ++++++++++ .../SourceIndexServer.csproj | 2 +- .../src/SourceIndexServer/wwwroot/index.html | 1 + 25 files changed, 179 insertions(+), 65 deletions(-) create mode 100644 src/SourceBrowser/src/SourceIndexServer/Controllers/OpenSearchController.cs diff --git a/global.json b/global.json index 6b13028..34ca777 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.404", + "version": "9.0.203", "rollForward": "major" } } diff --git a/src/SourceBrowser.hash b/src/SourceBrowser.hash index 6244b48..9373957 100644 --- a/src/SourceBrowser.hash +++ b/src/SourceBrowser.hash @@ -1 +1 @@ -2b57a3d551d02c05b90d006f48cfa07c0a7e5cd2 +bf64cd8ac09f60e605e1a86784da47cc2c034a89 diff --git a/src/SourceBrowser/.gitignore b/src/SourceBrowser/.gitignore index 501051f..efc8a11 100644 --- a/src/SourceBrowser/.gitignore +++ b/src/SourceBrowser/.gitignore @@ -25,6 +25,9 @@ bld/ # Visual Studo 2015 cache/options directory .vs/ +# Rider +.idea/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* diff --git a/src/SourceBrowser/TestCode/Project2/Class1.cs b/src/SourceBrowser/TestCode/Project2/Class1.cs index 8720fae..48f6b98 100644 --- a/src/SourceBrowser/TestCode/Project2/Class1.cs +++ b/src/SourceBrowser/TestCode/Project2/Class1.cs @@ -169,4 +169,18 @@ static TargetedTypeNewTest Create() { return new(new()); } -} \ No newline at end of file +} + +class TypeWithPrimaryConstructor(A a, B b) +{ + public A A => a; + public B[] ArrayOfB => [b]; +} + +class EmptyType; + +class TypeWithAllowsRefStruct + where T : allows ref struct +{ + public static T Return(T value) => value; +} diff --git a/src/SourceBrowser/src/BinLogParser/BinLogParser.csproj b/src/SourceBrowser/src/BinLogParser/BinLogParser.csproj index e36baec..c947fd6 100644 --- a/src/SourceBrowser/src/BinLogParser/BinLogParser.csproj +++ b/src/SourceBrowser/src/BinLogParser/BinLogParser.csproj @@ -1,7 +1,7 @@ - net472;net8.0 + net472;net9.0 BinLogParser Microsoft.SourceBrowser.BinLogParser diff --git a/src/SourceBrowser/src/BinLogToSln/BinLogToSln.csproj b/src/SourceBrowser/src/BinLogToSln/BinLogToSln.csproj index 9575971..bb477b8 100644 --- a/src/SourceBrowser/src/BinLogToSln/BinLogToSln.csproj +++ b/src/SourceBrowser/src/BinLogToSln/BinLogToSln.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 true Major true diff --git a/src/SourceBrowser/src/Common/Common.csproj b/src/SourceBrowser/src/Common/Common.csproj index 4761616..de08182 100644 --- a/src/SourceBrowser/src/Common/Common.csproj +++ b/src/SourceBrowser/src/Common/Common.csproj @@ -1,7 +1,7 @@  Microsoft.SourceBrowser.Common - net472;net8.0 + net472;net9.0 true ..\..\key.snk diff --git a/src/SourceBrowser/src/Common/PriorityQueue.cs b/src/SourceBrowser/src/Common/PriorityQueue.cs index d333ba5..9f74c3b 100644 --- a/src/SourceBrowser/src/Common/PriorityQueue.cs +++ b/src/SourceBrowser/src/Common/PriorityQueue.cs @@ -1,6 +1,12 @@ using System.Collections.Generic; using System.Diagnostics; +// WARNING: this class has a bug! +// See here for an explanation: +// https://github.com/dotnet/wpf/blob/bcd972664606974adc09f7f1b8c7a9a14c33c899/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/LegacyPriorityQueue.cs#L21 +// I don't care enough to switch to the new implementation, but it's important to leave this notice here. +// We copied the old code before the fix was made in the WPF sources. + namespace Microsoft.SourceBrowser.Common { /// @@ -207,4 +213,4 @@ public void PushRange(IEnumerable list) } } } -} \ No newline at end of file +} diff --git a/src/SourceBrowser/src/Directory.Packages.props b/src/SourceBrowser/src/Directory.Packages.props index 543cdfb..6619aff 100644 --- a/src/SourceBrowser/src/Directory.Packages.props +++ b/src/SourceBrowser/src/Directory.Packages.props @@ -7,25 +7,25 @@ - - - - + + + + - - - - - - - - - - + + + + + + + + + + @@ -40,7 +40,7 @@ - + @@ -48,22 +48,22 @@ - - + + - - - + + + - - + + - + - + diff --git a/src/SourceBrowser/src/HtmlGenerator/CommandLineOptions.cs b/src/SourceBrowser/src/HtmlGenerator/CommandLineOptions.cs index 9d900ee..7ebb813 100644 --- a/src/SourceBrowser/src/HtmlGenerator/CommandLineOptions.cs +++ b/src/SourceBrowser/src/HtmlGenerator/CommandLineOptions.cs @@ -22,7 +22,8 @@ public CommandLineOptions( IReadOnlyList pluginBlacklist, bool loadPlugins, bool excludeTests, - string rootPath) + string rootPath, + bool includeSourceGeneratedDocuments) { SolutionDestinationFolder = solutionDestinationFolder; Projects = projects; @@ -38,6 +39,7 @@ public CommandLineOptions( LoadPlugins = loadPlugins; ExcludeTests = excludeTests; RootPath = rootPath; + IncludeSourceGeneratedDocuments = includeSourceGeneratedDocuments; } public string SolutionDestinationFolder { get; } @@ -45,6 +47,7 @@ public CommandLineOptions( public IReadOnlyDictionary Properties { get; } public bool EmitAssemblyList { get; } public bool DoNotIncludeReferencedProjects { get; } + public bool IncludeSourceGeneratedDocuments { get; } public bool Force { get; } public bool NoBuiltInFederations { get; } public IReadOnlyDictionary OfflineFederations { get; } @@ -70,6 +73,7 @@ public static CommandLineOptions Parse(params string[] args) var pluginBlacklist = new List(); var loadPlugins = false; var excludeTests = false; + var includeSourceGeneratedDocuments = true; var rootPath = (string)null; foreach (var arg in args) @@ -216,6 +220,12 @@ public static CommandLineOptions Parse(params string[] args) continue; } + if (arg == "/excludeSourceGeneratedDocuments") + { + includeSourceGeneratedDocuments = false; + continue; + } + if (arg.StartsWith("/root:", StringComparison.Ordinal)) { rootPath = Path.GetFullPath(arg.Substring("/root:".Length).StripQuotes()); @@ -259,7 +269,8 @@ public static CommandLineOptions Parse(params string[] args) pluginBlacklist, loadPlugins, excludeTests, - rootPath); + rootPath, + includeSourceGeneratedDocuments); } private static void AddProject(List projects, string path) diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/Classifier.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/Classifier.cs index 8ff2257..680cd82 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/Classifier.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/Classifier.cs @@ -11,7 +11,7 @@ namespace Microsoft.SourceBrowser.HtmlGenerator { public partial class Classification { - public async Task> Classify(Document document, SourceText text) + public async Task> ClassifyAsync(Document document, SourceText text) { var span = TextSpan.FromBounds(0, text.Length); @@ -181,6 +181,7 @@ private Range CreateRange(SourceText text, TextSpan span, string classification) ["delegate name"] = Constants.ClassificationTypeName, ["record name"] = Constants.ClassificationTypeName, ["record class name"] = Constants.ClassificationTypeName, + ["record struct name"] = Constants.ClassificationTypeName, ["module name"] = Constants.ClassificationTypeName, ["type parameter name"] = Constants.ClassificationTypeName, ["preprocessor keyword"] = Constants.ClassificationPreprocessKeyword, diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.Links.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.Links.cs index 9276b2b..e9163fc 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.Links.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.Links.cs @@ -354,11 +354,12 @@ private void AddReferencesToImplementedMembers( { var declaringType = declaredSymbol.ContainingType; var interfaces = declaringType.AllInterfaces; + var comparer = SymbolEqualityComparer.Default; foreach (var implementedInterface in interfaces) { foreach (var member in implementedInterface.GetMembers()) { - if (declaredSymbol.Equals(declaringType.FindImplementationForInterfaceMember(member), SymbolEqualityComparer.Default)) + if (comparer.Equals(declaredSymbol, declaringType.FindImplementationForInterfaceMember(member))) { ProcessReference( range, diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.cs index aa95010..96244ed 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/DocumentGenerator.cs @@ -38,7 +38,7 @@ public DocumentGenerator( this.Document = document; } - public async Task Generate() + public async Task GenerateAsync() { if (Configuration.CalculateRoslynSemantics) { @@ -113,7 +113,7 @@ public async Task Generate() append: false, encoding: Encoding.UTF8)) { - await GenerateHtml(streamWriter); + await GenerateHtmlAsync(streamWriter); } } else @@ -121,7 +121,7 @@ public async Task Generate() using (var memoryStream = new MemoryStream()) using (var streamWriter = new StreamWriter(memoryStream)) { - await GeneratePre(streamWriter); + await GeneratePreAsync(streamWriter); } } } @@ -137,7 +137,7 @@ private void CalculateRelativePathToRoot() this.relativePathToRoot = Paths.CalculateRelativePathToRoot(documentDestinationFilePath, SolutionDestinationFolder); } - private async Task GenerateHtml(StreamWriter writer) + private async Task GenerateHtmlAsync(StreamWriter writer) { var title = Document.Name; var lineCount = Text.Lines.Count; @@ -151,7 +151,7 @@ private async Task GenerateHtml(StreamWriter writer) await writer.WriteAsync(prefix); GenerateHeader(writer.WriteLine); - var ranges = (await classifier.Classify(Document, Text))?.ToArray(); + var ranges = (await classifier.ClassifyAsync(Document, Text))?.ToArray(); // pass a value larger than 0 to generate line numbers statically at HTML generation time var table = Markup.GetTablePrefix( @@ -285,9 +285,9 @@ private void GenerateHeader(Action writeLine) projectLink: (Display: projectGenerator.ProjectSourcePath, Url: "/#" + Document.Project.AssemblyName, projectGenerator.AssemblyName)); } - private async Task GeneratePre(StreamWriter writer, int lineCount = 0) + private async Task GeneratePreAsync(StreamWriter writer, int lineCount = 0) { - var ranges = await classifier.Classify(Document, Text); + var ranges = await classifier.ClassifyAsync(Document, Text); GeneratePre(ranges, writer, lineCount); } diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/MetadataAsSource.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/MetadataAsSource.cs index ab00e1c..48216c9 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/MetadataAsSource.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/MetadataAsSource.cs @@ -16,7 +16,7 @@ public class MetadataAsSource { private static Func> addSourceToAsync = null; - private static Func> ReflectAddSourceToAsync(object service) + private static Func> ReflectAddSourceTo(object service) { var assembly = Assembly.Load("Microsoft.CodeAnalysis.Features"); var type = assembly.GetType("Microsoft.CodeAnalysis.MetadataAsSource.IMetadataAsSourceService"); @@ -87,7 +87,7 @@ public static Solution LoadMetadataAsSourceSolution(string assemblyFilePath) var metadataAsSourceService = WorkspaceHacks.GetMetadataAsSourceService(tempDocument); if (addSourceToAsync == null) { - addSourceToAsync = ReflectAddSourceToAsync(metadataAsSourceService); + addSourceToAsync = ReflectAddSourceTo(metadataAsSourceService); } var texts = new Dictionary(SymbolEqualityComparer.Default); diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/ProjectGenerator.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/ProjectGenerator.cs index 46c51a1..d4d46c3 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/ProjectGenerator.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/ProjectGenerator.cs @@ -81,7 +81,24 @@ private ProjectGenerator() this.OtherFiles = new List(); } - public async Task Generate() + private async IAsyncEnumerable GetDocumentsAsync() + { + foreach(var d in Project.Documents) + { + yield return d; + } + + if (SolutionGenerator.IncludeSourceGeneratedDocuments) + { + var generatedDocuments = await Project.GetSourceGeneratedDocumentsAsync(); + foreach(var document in generatedDocuments) + { + yield return document; + } + } + } + + public async Task GenerateAsync() { try { @@ -124,7 +141,14 @@ public async Task Generate() Directory.CreateDirectory(ProjectDestinationFolder); } - var documents = Project.Documents.Where(IncludeDocument).ToList(); + List documents = new(); + await foreach(var d in GetDocumentsAsync()) + { + if (IncludeDocument(d)) + { + documents.Add(d); + } + } var generationTasks = Partitioner.Create(documents) .GetPartitions(Environment.ProcessorCount) @@ -135,7 +159,7 @@ public async Task Generate() { while (partition.MoveNext()) { - await GenerateDocument(partition.Current); + await GenerateDocumentAsync(partition.Current); } } })); @@ -198,17 +222,17 @@ private void GenerateNamespaceExplorer() NamespaceExplorer.WriteNamespaceExplorer(this.AssemblyName, symbols, ProjectDestinationFolder); } - private Task GenerateDocument(Document document) + private async Task GenerateDocumentAsync(Document document) { try { var documentGenerator = new DocumentGenerator(this, document); - return documentGenerator.Generate(); + await documentGenerator.GenerateAsync(); } catch (Exception e) { Log.Exception(e, "Document generation failed for: " + (document.FilePath ?? document.ToString())); - return Task.FromResult(e); + throw; } } diff --git a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/SolutionGenerator.cs b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/SolutionGenerator.cs index bceb9e0..30c5b72 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/SolutionGenerator.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Pass1-Generation/SolutionGenerator.cs @@ -21,6 +21,8 @@ public partial class SolutionGenerator : IDisposable public string ProjectFilePath { get; private set; } public IReadOnlyDictionary ServerPathMappings { get; set; } private Federation Federation { get; set; } + public bool IncludeSourceGeneratedDocuments { get; } + public IEnumerable PluginBlacklist { get; private set; } private readonly HashSet typeScriptFiles = new HashSet(StringComparer.OrdinalIgnoreCase); public MEF.PluginAggregator PluginAggregator; @@ -42,6 +44,7 @@ public SolutionGenerator( IReadOnlyDictionary serverPathMappings = null, IEnumerable pluginBlacklist = null, bool doNotIncludeReferencedProjects = false, + bool includeSourceGeneratedDocuments = true, IReadOnlyDictionary, string> typeForwards = null) { this.SolutionSourceFolder = Path.GetDirectoryName(solutionFilePath); @@ -51,6 +54,7 @@ public SolutionGenerator( this.solution = CreateSolution(solutionFilePath, properties, doNotIncludeReferencedProjects); this.Federation = federation ?? new Federation(); this.PluginBlacklist = pluginBlacklist ?? Enumerable.Empty(); + this.IncludeSourceGeneratedDocuments = includeSourceGeneratedDocuments; this.Properties = properties; this.TypeForwards = typeForwards ?? ImmutableDictionary, string>.Empty; @@ -333,7 +337,7 @@ public bool Generate(HashSet processedAssemblyList = null, Folder serverPathMappings, IEnumerable pluginBlacklist, bool doNotIncludeReferencedProjects = false, - string rootPath = null) + string rootPath = null, + bool includeSourceGeneratedDocuments = true) { var assemblyNames = new HashSet(StringComparer.OrdinalIgnoreCase); @@ -230,6 +233,7 @@ private static void IndexSolutions( serverPathMappings: serverPathMappings, pluginBlacklist: pluginBlacklist, doNotIncludeReferencedProjects: doNotIncludeReferencedProjects, + includeSourceGeneratedDocuments: includeSourceGeneratedDocuments, typeForwards: typeForwards)) { solutionGenerator.GlobalAssemblyList = assemblyNames; diff --git a/src/SourceBrowser/src/HtmlGenerator/SourceBrowser.nuspec b/src/SourceBrowser/src/HtmlGenerator/SourceBrowser.nuspec index cd8488c..ab4686f 100644 --- a/src/SourceBrowser/src/HtmlGenerator/SourceBrowser.nuspec +++ b/src/SourceBrowser/src/HtmlGenerator/SourceBrowser.nuspec @@ -22,6 +22,8 @@ + + diff --git a/src/SourceBrowser/src/HtmlGenerator/Utilities/Paths.cs b/src/SourceBrowser/src/HtmlGenerator/Utilities/Paths.cs index ca6f90a..f41fa91 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Utilities/Paths.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Utilities/Paths.cs @@ -166,7 +166,7 @@ public static string GetRelativeFilePathInProject(Document document) .ToArray()); string fileName; - if (document.FilePath != null) + if (document.FilePath != null && !document.GetLinkedDocumentIds().Any()) { fileName = Path.GetFileName(document.FilePath); } diff --git a/src/SourceBrowser/src/HtmlGenerator/Utilities/WorkspaceHacks.cs b/src/SourceBrowser/src/HtmlGenerator/Utilities/WorkspaceHacks.cs index 2a22522..98e6273 100644 --- a/src/SourceBrowser/src/HtmlGenerator/Utilities/WorkspaceHacks.cs +++ b/src/SourceBrowser/src/HtmlGenerator/Utilities/WorkspaceHacks.cs @@ -9,12 +9,12 @@ public static class WorkspaceHacks { public static dynamic GetSemanticFactsService(Document document) { - return GetService(document, "Microsoft.CodeAnalysis.LanguageServices.ISemanticFactsService", "Microsoft.CodeAnalysis.Workspaces"); + return GetService(document, "Microsoft.CodeAnalysis.LanguageService.ISemanticFactsService", "Microsoft.CodeAnalysis.Workspaces"); } public static dynamic GetSyntaxFactsService(Document document) { - return GetService(document, "Microsoft.CodeAnalysis.LanguageServices.ISyntaxFactsService", "Microsoft.CodeAnalysis.Workspaces"); + return GetService(document, "Microsoft.CodeAnalysis.LanguageService.ISyntaxFactsService", "Microsoft.CodeAnalysis.Workspaces"); } public static object GetMetadataAsSourceService(Document document) @@ -33,7 +33,7 @@ private static object GetService(Workspace workspace, string language, Type serv var languageServicesType = typeof(HostLanguageServices); var genericMethod = languageServicesType.GetMethod("GetService", BindingFlags.Public | BindingFlags.Instance); var closedGenericMethod = genericMethod.MakeGenericMethod(serviceType); - var result = closedGenericMethod.Invoke(languageServices, new object[0]); + var result = closedGenericMethod.Invoke(languageServices, Array.Empty()); if (result == null) { throw new NullReferenceException("Unable to get language service: " + serviceType.FullName + " for " + language); @@ -44,13 +44,11 @@ private static object GetService(Workspace workspace, string language, Type serv private static object GetService(Document document, string serviceType, string assemblyName) { - var assembly = typeof(Document).Assembly; - var documentExtensions = assembly.GetType("Microsoft.CodeAnalysis.Shared.Extensions.DocumentExtensions"); var serviceAssembly = Assembly.Load(assemblyName); var serviceInterfaceType = serviceAssembly.GetType(serviceType); - var getLanguageServiceMethod = documentExtensions.GetMethod("GetLanguageService", new Type[] { typeof(Document) }); - getLanguageServiceMethod = getLanguageServiceMethod.MakeGenericMethod(serviceInterfaceType); - var service = getLanguageServiceMethod.Invoke(null, new object[] { document }); + var genericMethod = typeof(LanguageServices).GetMethod(nameof(LanguageServices.GetService), BindingFlags.Public | BindingFlags.Instance); + var closedGenericMethod = genericMethod.MakeGenericMethod(serviceInterfaceType); + var service = closedGenericMethod.Invoke(document.Project.Services, Array.Empty()); return service; } } diff --git a/src/SourceBrowser/src/HtmlGenerator/app.config b/src/SourceBrowser/src/HtmlGenerator/app.config index 86a8297..4b45edc 100644 --- a/src/SourceBrowser/src/HtmlGenerator/app.config +++ b/src/SourceBrowser/src/HtmlGenerator/app.config @@ -8,5 +8,24 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SourceBrowser/src/SourceIndexServer.Tests/SourceIndexServer.Tests.csproj b/src/SourceBrowser/src/SourceIndexServer.Tests/SourceIndexServer.Tests.csproj index 66e51be..95a8f8e 100644 --- a/src/SourceBrowser/src/SourceIndexServer.Tests/SourceIndexServer.Tests.csproj +++ b/src/SourceBrowser/src/SourceIndexServer.Tests/SourceIndexServer.Tests.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 diff --git a/src/SourceBrowser/src/SourceIndexServer/Controllers/OpenSearchController.cs b/src/SourceBrowser/src/SourceIndexServer/Controllers/OpenSearchController.cs new file mode 100644 index 0000000..39561bd --- /dev/null +++ b/src/SourceBrowser/src/SourceIndexServer/Controllers/OpenSearchController.cs @@ -0,0 +1,26 @@ +using System; +using System.Text; +using Microsoft.AspNetCore.Mvc; + +namespace Microsoft.SourceBrowser.SourceIndexServer.Controllers +{ + [ApiController] + public class OpenSearchController : Controller + { + [HttpGet("/opensearch")] + public IActionResult GetOpenSearchDescriptionDocument() + { + var pathBase = String.IsNullOrWhiteSpace(Request.PathBase) ? "" : "/" + Request.PathBase; + var urlBase = $"{Request.Scheme}://{Request.Host}{pathBase}"; + var result = String.Join("\r\n", + "", + "", + " Source Browser", + $" {urlBase}/favicon.ico", + $" ", + "" + ); + return Content(result, "application/opensearchdescription+xml", Encoding.UTF8); + } + } +} diff --git a/src/SourceBrowser/src/SourceIndexServer/SourceIndexServer.csproj b/src/SourceBrowser/src/SourceIndexServer/SourceIndexServer.csproj index ccd90e9..d2fe663 100644 --- a/src/SourceBrowser/src/SourceIndexServer/SourceIndexServer.csproj +++ b/src/SourceBrowser/src/SourceIndexServer/SourceIndexServer.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 Microsoft.SourceBrowser.SourceIndexServer Microsoft.SourceBrowser.SourceIndexServer OutOfProcess diff --git a/src/SourceBrowser/src/SourceIndexServer/wwwroot/index.html b/src/SourceBrowser/src/SourceIndexServer/wwwroot/index.html index 7dd3bc8..bcac4c3 100644 --- a/src/SourceBrowser/src/SourceIndexServer/wwwroot/index.html +++ b/src/SourceBrowser/src/SourceIndexServer/wwwroot/index.html @@ -3,6 +3,7 @@ Source Browser + From ac0a35b666c85ed184a4d10ca556f8ed57e62bea Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 30 Apr 2025 18:19:25 +0200 Subject: [PATCH 2/2] Use .NET from global.json in CI --- .github/workflows/dotnet.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index eeee5fe..eb7fb90 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -10,11 +10,11 @@ jobs: build: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '8.0.x' + global-json-file: global.json - name: Restore source-indexer.sln run: dotnet restore src/source-indexer.sln - name: Build source-indexer.sln