Skip to content

Commit

Permalink
Add support for Miscellaneous Files (#1252)
Browse files Browse the repository at this point in the history
* Basic of the orphan file system

* Initialise the project system

* add csproj

* Test using MSBuildProjectSystem

* Orphan file system using the msbuild system

* Remove unnecessary change

* csproj temp

* Get only syntactic diagnostics for misc files

* Logic to delete the document

* Edit csproj

* Rename to misc files

* Order the project systems

* Ordering failing

* Order project systems based on DisplayName

* Remove orphan system

* Put inside the partial class

* Clean up the miscellanous file system

* Tests for the misc project system

* Make MEF work

* Returns only semantic diagnostics running

* Add more failing tests

* Clean up

* Extension Ordering working for the project systems

* Clean the solution

* Change the target framework

* Add references

* Rename project system

* Add few tests

* Refactor the tests to add a method to the test host

* Remove roslyn dependency in abstractions

* use only one project for all the miscellanous files

* Add project system names class

* Modifying the files changed facts to use absolute path instead of relative

By adding the misc files support, the file that was being added by the test was being treated as a miscellanous file and being added to the workspace. However since the path being passed was relative, an exception was being thrown.

* Add the empty project

* Add the IUpdates interface

* Add absolute paths for the misc file system

* Add dotnet project system for the updates

* CR feedback

* Remove comment

* Add project handling in the workspace

* Add assembly info

* Deal with race condition between project system updates

* add property type

* CR feedback

* Move the check for the Misc files into the workspace

* edit comment

* Check for the project id for the document

* Dont keep track of the documents in the project system

* Add test for multiple files

* Add test to handle deletion

* Call TryRemoveMiscDocument

* Naming consistency

* Use the default references same as the script system

* CR feedback
  • Loading branch information
akshita31 authored Aug 13, 2018
1 parent 1779733 commit 426ba08
Show file tree
Hide file tree
Showing 31 changed files with 945 additions and 248 deletions.
33 changes: 32 additions & 1 deletion OmniSharp.sln
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2005
Expand All @@ -11,7 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
global.json = global.json
EndProjectSection
ProjectSection(FolderGlobals) = preProject
global_1json__JSONSchema = http://json.schemastore.org/global
global_1json__JSONSchema = http://json.schemastore.org/global
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35E025BF-BBB2-4FAC-9F4B-37CBA083EE47}"
Expand Down Expand Up @@ -68,6 +69,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Stdio.Driver", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OmniSharp.Script.Tests", "tests\OmniSharp.Script.Tests\OmniSharp.Script.Tests.csproj", "{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniSharp.MiscellaneousFiles", "src\OmniSharp.MiscellaneousFiles\OmniSharp.MiscellaneousFiles.csproj", "{49358F28-883B-4FA0-B853-8774A732E188}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmniSharp.MiscellaneousFiles.Tests", "tests\OmniSharp.MiscellaneousFiles.Tests\OmniSharp.MiscellaneousFiles.Tests.csproj", "{51F1D224-A543-48C5-BD37-139B935E71D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -390,6 +395,30 @@ Global
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x64.Build.0 = Release|Any CPU
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x86.ActiveCfg = Release|Any CPU
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F}.Release|x86.Build.0 = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|x64.ActiveCfg = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|x64.Build.0 = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|x86.ActiveCfg = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Debug|x86.Build.0 = Debug|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|Any CPU.Build.0 = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|x64.ActiveCfg = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|x64.Build.0 = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|x86.ActiveCfg = Release|Any CPU
{49358F28-883B-4FA0-B853-8774A732E188}.Release|x86.Build.0 = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|x64.ActiveCfg = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|x64.Build.0 = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|x86.ActiveCfg = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Debug|x86.Build.0 = Debug|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|Any CPU.Build.0 = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|x64.ActiveCfg = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|x64.Build.0 = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|x86.ActiveCfg = Release|Any CPU
{51F1D224-A543-48C5-BD37-139B935E71D8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -421,6 +450,8 @@ Global
{BC640CBF-F6E2-42EA-9D61-FB6E515AEA44} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{D2A78CEE-B278-476F-AF34-A7D6F792F973} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{9E4BA68C-7F4B-429A-A0C7-8CE7D41D610F} = {35E025BF-BBB2-4FAC-9F4B-37CBA083EE47}
{49358F28-883B-4FA0-B853-8774A732E188} = {2C348365-A9D8-459E-9276-56FC46AAEE31}
{51F1D224-A543-48C5-BD37-139B935E71D8} = {35E025BF-BBB2-4FAC-9F4B-37CBA083EE47}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4DD725CE-B49A-4151-8B77-BB33FE88E46E}
Expand Down
18 changes: 18 additions & 0 deletions src/OmniSharp.Abstractions/Mef/ExportProjectSystemAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Composition;
using OmniSharp.Services;

namespace OmniSharp.Mef
{
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportProjectSystemAttribute: ExportAttribute
{
public string Name { get; }

public ExportProjectSystemAttribute(string name) : base(typeof(IProjectSystem))
{
Name = name;
}
}
}
7 changes: 7 additions & 0 deletions src/OmniSharp.Abstractions/Mef/ProjectSystemMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace OmniSharp.Mef
{
public class ProjectSystemMetadata
{
public string Name { get; set; }
}
}
11 changes: 11 additions & 0 deletions src/OmniSharp.Abstractions/ProjectSystemNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace OmniSharp
{
public static class ProjectSystemNames
{
public const string MSBuildProjectSystem = "MSBuildProjectSystem";
public const string CakeProjectSystem = "CakeProjectSystem";
public const string DotNetProjectSystem = "DotNetProjectSystem";
public const string ScriptProjectSystem = "ScriptProjectSystem";
public const string MiscellaneousFilesProjectSystem = "MiscellaneousFilesProjectSystem";
}
}
9 changes: 9 additions & 0 deletions src/OmniSharp.Abstractions/Services/IUpdates.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Threading.Tasks;

namespace OmniSharp.Services
{
public interface IWaitableProjectSystem: IProjectSystem
{
Task WaitForUpdatesAsync();
}
}
3 changes: 2 additions & 1 deletion src/OmniSharp.Cake/CakeProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Helpers;
using OmniSharp.Mef;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Services;

namespace OmniSharp.Cake
{
[Export(typeof(IProjectSystem)), Shared]
[ExportProjectSystem(ProjectSystemNames.CakeProjectSystem), Shared]
public class CakeProjectSystem : IProjectSystem
{
private readonly OmniSharpWorkspace _workspace;
Expand Down
10 changes: 8 additions & 2 deletions src/OmniSharp.DotNet/DotNetProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
using OmniSharp.Eventing;
using OmniSharp.FileWatching;
using OmniSharp.Helpers;
using OmniSharp.Mef;
using OmniSharp.Models.Events;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.Services;

namespace OmniSharp.DotNet
{
[Export(typeof(IProjectSystem)), Shared]
public class DotNetProjectSystem : IProjectSystem
[ExportProjectSystem(ProjectSystemNames.DotNetProjectSystem), Shared]
public class DotNetProjectSystem : IWaitableProjectSystem
{
private const string CompilationConfiguration = "Debug";

Expand Down Expand Up @@ -423,5 +424,10 @@ private static LanguageVersion ParseLanguageVersion(string value)

return languageVersion;
}

async Task IWaitableProjectSystem.WaitForUpdatesAsync()
{
await ((IProjectSystem)this).GetWorkspaceModelAsync(new WorkspaceInformationRequest());
}
}
}
9 changes: 7 additions & 2 deletions src/OmniSharp.Host/WorkspaceInitializer.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System;
using System.Composition.Hosting;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OmniSharp.Mef;
using OmniSharp.Options;
using OmniSharp.Roslyn;
using OmniSharp.Roslyn.Options;
using OmniSharp.Services;
using OmniSharp.Utilities;

namespace OmniSharp
{
Expand All @@ -24,9 +27,11 @@ public static void Initialize(

var projectEventForwarder = compositionHost.GetExport<ProjectEventForwarder>();
projectEventForwarder.Initialize();
var projectSystems = compositionHost.GetExports<Lazy<IProjectSystem, ProjectSystemMetadata>>();
var ps = projectSystems.Select(n => n.Value);
var orderedProjectSystems = ExtensionOrderer.GetOrderedOrUnorderedList<IProjectSystem, ExportProjectSystemAttribute>(ps, eps => eps.Name);

// Initialize all the project systems
foreach (var projectSystem in compositionHost.GetExports<IProjectSystem>())
foreach (var projectSystem in orderedProjectSystems)
{
try
{
Expand Down
10 changes: 8 additions & 2 deletions src/OmniSharp.MSBuild/ProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using OmniSharp.Eventing;
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Mef;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.MSBuild.Discovery;
using OmniSharp.MSBuild.Models;
Expand All @@ -20,8 +21,8 @@

namespace OmniSharp.MSBuild
{
[Export(typeof(IProjectSystem)), Shared]
public class ProjectSystem : IProjectSystem
[ExportProjectSystem(ProjectSystemNames.MSBuildProjectSystem), Shared]
public class ProjectSystem : IWaitableProjectSystem
{
private readonly IOmniSharpEnvironment _environment;
private readonly OmniSharpWorkspace _workspace;
Expand Down Expand Up @@ -209,5 +210,10 @@ async Task<object> IProjectSystem.GetProjectModelAsync(string filePath)

return new MSBuildProjectInfo(projectFileInfo);
}

public async Task WaitForUpdatesAsync()
{
await _manager.WaitForQueueEmptyAsync();
}
}
}
111 changes: 111 additions & 0 deletions src/OmniSharp.MiscellaneousFiles/MiscellaneousFilesProjectSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Composition;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Mef;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.Services;

namespace OmniSharp.MiscellaneousFile
{
[ExtensionOrder(After = ProjectSystemNames.MSBuildProjectSystem)]
[ExtensionOrder(After = ProjectSystemNames.DotNetProjectSystem)]
[ExportProjectSystem(ProjectSystemNames.MiscellaneousFilesProjectSystem), Shared]
public class MiscellaneousFilesProjectSystem : IProjectSystem
{
private const string miscFileExtension = ".cs";
public string Key => ProjectSystemNames.MiscellaneousFilesProjectSystem;
public string Language => LanguageNames.CSharp;
IEnumerable<string> IProjectSystem.Extensions => new[] { miscFileExtension };
public bool EnabledByDefault { get; } = true;

private readonly OmniSharpWorkspace _workspace;
private readonly IFileSystemWatcher _fileSystemWatcher;
private readonly FileSystemHelper _fileSystemHelper;
private readonly List<IWaitableProjectSystem> _projectSystems;
private readonly ILogger _logger;

[ImportingConstructor]
public MiscellaneousFilesProjectSystem(OmniSharpWorkspace workspace, IFileSystemWatcher fileSystemWatcher, FileSystemHelper fileSystemHelper,
ILoggerFactory loggerFactory, [ImportMany] IEnumerable<Lazy<IProjectSystem, ProjectSystemMetadata>> projectSystems)
{
_workspace = workspace;
_fileSystemWatcher = fileSystemWatcher;
_fileSystemHelper = fileSystemHelper;
_logger = loggerFactory.CreateLogger<MiscellaneousFilesProjectSystem>();
_projectSystems = projectSystems
.Where(ps => ps.Metadata.Name == ProjectSystemNames.MSBuildProjectSystem ||
ps.Metadata.Name == ProjectSystemNames.DotNetProjectSystem)
.Select(ps => ps.Value)
.Cast<IWaitableProjectSystem>()
.ToList();
}

Task<object> IProjectSystem.GetProjectModelAsync(string filePath)
{
return Task.FromResult<object>(null);
}

Task<object> IProjectSystem.GetWorkspaceModelAsync(WorkspaceInformationRequest request)
{
return Task.FromResult<object>(null);
}

void IProjectSystem.Initalize(IConfiguration configuration)
{
var allFiles = _fileSystemHelper.GetFiles("**/*.cs");
foreach (var filePath in allFiles)
TryAddMiscellaneousFile(filePath);

_fileSystemWatcher.Watch(miscFileExtension, OnMiscellaneousFileChanged);
}

private async void TryAddMiscellaneousFile(string filePath)
{
//wait for the project systems to finish processing the updates
foreach (var projectSystem in _projectSystems)
{
await projectSystem.WaitForUpdatesAsync();
}

var absoluteFilePath = new FileInfo(filePath).FullName;
if (!File.Exists(absoluteFilePath))
return;

if (_workspace.TryAddMiscellaneousDocument(absoluteFilePath, Language) != null)
{
_logger.LogInformation($"Successfully added file '{absoluteFilePath}' to workspace");
}
}

private void OnMiscellaneousFileChanged(string filePath, FileChangeType changeType)
{
if (changeType == FileChangeType.Unspecified && File.Exists(filePath) ||
changeType == FileChangeType.Create)
{
TryAddMiscellaneousFile(filePath);
}

else if (changeType == FileChangeType.Unspecified && !File.Exists(filePath) ||
changeType == FileChangeType.Delete)
{
RemoveFromWorkspace(filePath);
}
}

private void RemoveFromWorkspace(string filePath)
{
if (_workspace.TryRemoveMiscellaneousDocument(filePath))
{
_logger.LogDebug($"Removed file '{filePath}' from the workspace.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\OmniSharp.Abstractions\OmniSharp.Abstractions.csproj" />
<ProjectReference Include="..\OmniSharp.Roslyn\OmniSharp.Roslyn.csproj" />
</ItemGroup>

</Project>
15 changes: 12 additions & 3 deletions src/OmniSharp.Roslyn.CSharp/Helpers/DiagnosticExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,24 @@ internal static DiagnosticLocation ToDiagnosticLocation(this Diagnostic diagnost
};
}

internal static async Task<IEnumerable<DiagnosticLocation>> FindDiagnosticLocationsAsync(this IEnumerable<Document> documents)
internal static async Task<IEnumerable<DiagnosticLocation>> FindDiagnosticLocationsAsync(this IEnumerable<Document> documents, OmniSharpWorkspace workspace)
{
if (documents == null || !documents.Any()) return Enumerable.Empty<DiagnosticLocation>();

var items = new List<DiagnosticLocation>();
foreach (var document in documents)
{
var semanticModel = await document.GetSemanticModelAsync();
IEnumerable<Diagnostic> diagnostics = semanticModel.GetDiagnostics();
IEnumerable<Diagnostic> diagnostics;
if (workspace.IsCapableOfSemanticDiagnostics(document))
{
var semanticModel = await document.GetSemanticModelAsync();
diagnostics = semanticModel.GetDiagnostics();
}
else
{
var syntaxModel = await document.GetSyntaxTreeAsync();
diagnostics = syntaxModel.GetDiagnostics();
}

foreach (var quickFix in diagnostics.Select(d => d.ToDiagnosticLocation()))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async Task<QuickFixResponse> Handle(CodeCheckRequest request)
? _workspace.GetDocuments(request.FileName)
: _workspace.CurrentSolution.Projects.SelectMany(project => project.Documents);

var quickFixes = await documents.FindDiagnosticLocationsAsync();
var quickFixes = await documents.FindDiagnosticLocationsAsync(_workspace);
return new QuickFixResponse(quickFixes);
}
}
Expand Down
Loading

0 comments on commit 426ba08

Please sign in to comment.