From ed4e7c1417d45b60e8180e79d3722e3e4b10136c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Wed, 6 Dec 2017 00:37:03 +0200 Subject: [PATCH 1/3] Check if file exist before trying to create MetadataReference. --- src/OmniSharp.Cake/CakeProjectSystem.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/OmniSharp.Cake/CakeProjectSystem.cs b/src/OmniSharp.Cake/CakeProjectSystem.cs index e0f4a1aee4..3fb25627e4 100644 --- a/src/OmniSharp.Cake/CakeProjectSystem.cs +++ b/src/OmniSharp.Cake/CakeProjectSystem.cs @@ -148,7 +148,7 @@ private void ScriptReferencesChanged(object sender, ReferencesChangedEventArgs e var document = solution.GetDocument(documentId); var project = document.Project; - var metadataReferences = e.References.Select(reference => MetadataReference.CreateFromFile(reference, documentation: GetDocumentationProvider(reference))); + var metadataReferences = GetMetadataReferences(e.References); var fileReferencesToRemove = project.MetadataReferences; foreach (var reference in metadataReferences) @@ -217,12 +217,26 @@ private ProjectInfo GetProject(CakeScript cakeScript, string filePath) language: LanguageNames.CSharp, compilationOptions: cakeScript.Usings == null ? _compilationOptions.Value : _compilationOptions.Value.WithUsings(cakeScript.Usings), parseOptions: new CSharpParseOptions(LanguageVersion.Default, DocumentationMode.Parse, SourceCodeKind.Script), - metadataReferences: cakeScript.References.Select(reference => MetadataReference.CreateFromFile(reference, documentation: GetDocumentationProvider(reference))), + metadataReferences: GetMetadataReferences(cakeScript.References), // TODO: projectReferences? isSubmission: true, hostObjectType: hostObjectType); } + private IEnumerable GetMetadataReferences(IEnumerable references) + { + foreach (var reference in references) + { + if (!File.Exists(reference)) + { + _logger.LogWarning($"Unable to create MetadataReference. File {reference} does not exist."); + continue; + } + + yield return MetadataReference.CreateFromFile(reference, documentation: GetDocumentationProvider(reference)); + } + } + private static DocumentationProvider GetDocumentationProvider(string assemblyPath) { var assemblyDocumentationPath = Path.ChangeExtension(assemblyPath, ".xml"); From 75e51e60408edf8e4011356d4bf97fdd3cc5c489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Thu, 7 Dec 2017 22:01:36 +0200 Subject: [PATCH 2/3] Use MetadataFileReferenceCache - Use MetadataFileReferenceCache when loading metadatareferences - ReferencesChangedEventArgs.References should be of type ISet --- src/OmniSharp.Cake/CakeProjectSystem.cs | 13 ++++--------- src/OmniSharp.Cake/Services/CakeScriptService.cs | 2 +- src/OmniSharp.Cake/Services/ICakeScriptService.cs | 6 +++--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/OmniSharp.Cake/CakeProjectSystem.cs b/src/OmniSharp.Cake/CakeProjectSystem.cs index 3fb25627e4..43ac92248d 100644 --- a/src/OmniSharp.Cake/CakeProjectSystem.cs +++ b/src/OmniSharp.Cake/CakeProjectSystem.cs @@ -23,6 +23,7 @@ namespace OmniSharp.Cake public class CakeProjectSystem : IProjectSystem { private readonly OmniSharpWorkspace _workspace; + private readonly MetadataFileReferenceCache _metadataReferenceCache; private readonly IOmniSharpEnvironment _environment; private readonly IAssemblyLoader _assemblyLoader; private readonly ICakeScriptService _scriptService; @@ -37,12 +38,14 @@ public class CakeProjectSystem : IProjectSystem [ImportingConstructor] public CakeProjectSystem( OmniSharpWorkspace workspace, + MetadataFileReferenceCache metadataReferenceCache, IOmniSharpEnvironment environment, IAssemblyLoader assemblyLoader, ICakeScriptService scriptService, ILoggerFactory loggerFactory) { _workspace = workspace ?? throw new ArgumentNullException(nameof(workspace)); + _metadataReferenceCache = metadataReferenceCache ?? throw new ArgumentNullException(nameof(metadataReferenceCache)); _environment = environment ?? throw new ArgumentNullException(nameof(environment)); _assemblyLoader = assemblyLoader ?? throw new ArgumentNullException(nameof(assemblyLoader)); _scriptService = scriptService ?? throw new ArgumentNullException(nameof(scriptService)); @@ -233,18 +236,10 @@ private IEnumerable GetMetadataReferences(IEnumerable continue; } - yield return MetadataReference.CreateFromFile(reference, documentation: GetDocumentationProvider(reference)); + yield return _metadataReferenceCache.GetMetadataReference(reference); } } - private static DocumentationProvider GetDocumentationProvider(string assemblyPath) - { - var assemblyDocumentationPath = Path.ChangeExtension(assemblyPath, ".xml"); - return File.Exists(assemblyDocumentationPath) - ? XmlDocumentationProvider.CreateFromFile(assemblyDocumentationPath) - : DocumentationProvider.Default; - } - private static CSharpCompilationOptions CreateCompilationOptions() { var compilationOptions = new CSharpCompilationOptions( diff --git a/src/OmniSharp.Cake/Services/CakeScriptService.cs b/src/OmniSharp.Cake/Services/CakeScriptService.cs index 68f9dcc66d..4003d19ece 100644 --- a/src/OmniSharp.Cake/Services/CakeScriptService.cs +++ b/src/OmniSharp.Cake/Services/CakeScriptService.cs @@ -65,7 +65,7 @@ public CakeScript Generate(FileChange fileChange) if (!cakeScript.References.SetEquals(references)) { _cachedReferences[fileChange.FileName] = cakeScript.References; - OnReferencesChanged(new ReferencesChangedEventArgs(fileChange.FileName, cakeScript.References.ToList())); + OnReferencesChanged(new ReferencesChangedEventArgs(fileChange.FileName, cakeScript.References)); } // Check if usings changed diff --git a/src/OmniSharp.Cake/Services/ICakeScriptService.cs b/src/OmniSharp.Cake/Services/ICakeScriptService.cs index a7e47f4fc4..6178d9bf4a 100644 --- a/src/OmniSharp.Cake/Services/ICakeScriptService.cs +++ b/src/OmniSharp.Cake/Services/ICakeScriptService.cs @@ -30,11 +30,11 @@ protected ScriptChangedEventArgs(string scriptPath) public class ReferencesChangedEventArgs : ScriptChangedEventArgs { - public IReadOnlyCollection References { get; } + public ISet References { get; } - public ReferencesChangedEventArgs(string scriptPath, IReadOnlyCollection references) : base(scriptPath) + public ReferencesChangedEventArgs(string scriptPath, ISet references) : base(scriptPath) { - References = references ?? new List(); + References = references ?? new HashSet(); } } From 03462929f7432708c972038d03b98aec5976e31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Thu, 7 Dec 2017 23:32:53 +0200 Subject: [PATCH 3/3] Avoid loading duplicate MetadataReferences --- src/OmniSharp.Cake/CakeProjectSystem.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/OmniSharp.Cake/CakeProjectSystem.cs b/src/OmniSharp.Cake/CakeProjectSystem.cs index 43ac92248d..5c7835f203 100644 --- a/src/OmniSharp.Cake/CakeProjectSystem.cs +++ b/src/OmniSharp.Cake/CakeProjectSystem.cs @@ -15,6 +15,7 @@ using OmniSharp.Cake.Services; using OmniSharp.Helpers; using OmniSharp.Models.WorkspaceInformation; +using OmniSharp.Roslyn.Utilities; using OmniSharp.Services; namespace OmniSharp.Cake @@ -152,14 +153,26 @@ private void ScriptReferencesChanged(object sender, ReferencesChangedEventArgs e var project = document.Project; var metadataReferences = GetMetadataReferences(e.References); - var fileReferencesToRemove = project.MetadataReferences; + var referencesToRemove = new HashSet(project.MetadataReferences, MetadataReferenceEqualityComparer.Instance); + var referencesToAdd = new HashSet(MetadataReferenceEqualityComparer.Instance); foreach (var reference in metadataReferences) { + if (referencesToRemove.Remove(reference)) + { + continue; + } + + if (referencesToAdd.Contains(reference)) + { + continue; + } + _workspace.AddMetadataReference(project.Id, reference); + referencesToAdd.Add(reference); } - foreach (var reference in fileReferencesToRemove) + foreach (var reference in referencesToRemove) { _workspace.RemoveMetadataReference(project.Id, reference); }