Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for aliases on both ProjectReference and Reference #1701

Merged
merged 4 commits into from
Feb 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private class ProjectData
public ImmutableArray<string> AdditionalFiles { get; }
public RuleSet RuleSet { get; }
public ImmutableDictionary<string, string> ReferenceAliases { get; }
public ImmutableDictionary<string, string> ProjectReferenceAliases { get; }
public bool TreatWarningsAsErrors { get; }
public string DefaultNamespace { get; }

Expand All @@ -68,6 +69,7 @@ private ProjectData()
Analyzers = ImmutableArray<string>.Empty;
AdditionalFiles = ImmutableArray<string>.Empty;
ReferenceAliases = ImmutableDictionary<string, string>.Empty;
ProjectReferenceAliases = ImmutableDictionary<string, string>.Empty;
}

private ProjectData(
Expand Down Expand Up @@ -148,7 +150,8 @@ private ProjectData(
bool treatWarningsAsErrors,
string defaultNamespace,
RuleSet ruleset,
ImmutableDictionary<string, string> referenceAliases)
ImmutableDictionary<string, string> referenceAliases,
ImmutableDictionary<string, string> projectReferenceAliases)
: this(guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, ruleset)
Expand All @@ -160,6 +163,7 @@ private ProjectData(
Analyzers = analyzers.EmptyIfDefault();
AdditionalFiles = additionalFiles.EmptyIfDefault();
ReferenceAliases = referenceAliases;
ProjectReferenceAliases = projectReferenceAliases;
}

public static ProjectData Create(MSB.Evaluation.Project project)
Expand Down Expand Up @@ -243,8 +247,24 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
var sourceFiles = GetFullPaths(
projectInstance.GetItems(ItemNames.Compile), filter: FileNameIsNotGenerated);

var projectReferences = GetFullPaths(
projectInstance.GetItems(ItemNames.ProjectReference), filter: IsCSharpProject);
var projectReferences = ImmutableArray.CreateBuilder<string>();
var projectReferenceAliases = ImmutableDictionary.CreateBuilder<string, string>();
var projectReferencesAdded = new HashSet<string>();
foreach (var projectReferenceItem in projectInstance.GetItems(ItemNames.ProjectReference))
{
var fullPath = projectReferenceItem.GetMetadataValue(MetadataNames.FullPath);

if (IsCSharpProject(fullPath) && projectReferencesAdded.Add(fullPath))
{
projectReferences.Add(fullPath);

var aliases = projectReferenceItem.GetMetadataValue(MetadataNames.Aliases);
if (!string.IsNullOrEmpty(aliases))
{
projectReferenceAliases[fullPath] = aliases;
}
}
}

var references = ImmutableArray.CreateBuilder<string>();
var referenceAliases = ImmutableDictionary.CreateBuilder<string, string>();
Expand Down Expand Up @@ -272,11 +292,12 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
if (!string.IsNullOrEmpty(fullPath))
{
references.Add(fullPath);
}
var aliases = referencePathItem.GetMetadataValue(MetadataNames.Aliases);
if(!string.IsNullOrEmpty(aliases))
{
referenceAliases[referencePathItem.EvaluatedInclude] = aliases;

var aliases = referencePathItem.GetMetadataValue(MetadataNames.Aliases);
if (!string.IsNullOrEmpty(aliases))
{
referenceAliases[fullPath] = aliases;
}
}
}

Expand All @@ -289,7 +310,8 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
configuration, platform, targetFramework, targetFrameworks,
outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow, documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds,
signAssembly, assemblyOriginatorKeyFile,
sourceFiles, projectReferences, references.ToImmutable(), packageReferences, analyzers, additionalFiles, treatWarningsAsErrors, defaultNamespace, ruleset, referenceAliases.ToImmutableDictionary());
sourceFiles, projectReferences.ToImmutable(), references.ToImmutable(), packageReferences, analyzers, additionalFiles, treatWarningsAsErrors, defaultNamespace, ruleset,
referenceAliases.ToImmutableDictionary(), projectReferenceAliases.ToImmutable());
}

private static RuleSet ResolveRulesetIfAny(MSB.Execution.ProjectInstance projectInstance)
Expand Down
1 change: 1 addition & 0 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ internal partial class ProjectFileInfo
public ImmutableArray<string> Analyzers => _data.Analyzers;
public ImmutableArray<string> AdditionalFiles => _data.AdditionalFiles;
public ImmutableDictionary<string, string> ReferenceAliases => _data.ReferenceAliases;
public ImmutableDictionary<string, string> ProjectReferenceAliases => _data.ProjectReferenceAliases;
public bool TreatWarningsAsErrors => _data.TreatWarningsAsErrors;
public string DefaultNamespace => _data.DefaultNamespace;

Expand Down
21 changes: 19 additions & 2 deletions src/OmniSharp.MSBuild/ProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,24 @@ private void UpdateProjectReferences(Project project, ImmutableArray<string> pro
continue;
}

var projectReference = new ProjectReference(referencedProject.Id);
ImmutableArray<string> aliases = default;
if (_projectFiles.TryGetValue(project.FilePath, out var projectFileInfo))
{
if (projectFileInfo.ProjectReferenceAliases.TryGetValue(projectReferencePath, out var projectReferenceAliases))
{
if (!string.IsNullOrEmpty(projectReferenceAliases))
{
aliases = projectReferenceAliases.Split(';').ToImmutableArray();
_logger.LogDebug($"Setting aliases: {projectReferencePath}, {projectReferenceAliases} ");
}
}
}
else
{
_logger.LogDebug($"failed to get project info:{project.FilePath}");
}

var projectReference = new ProjectReference(referencedProject.Id, aliases);

if (existingProjectReferences.Remove(projectReference))
{
Expand Down Expand Up @@ -659,7 +676,7 @@ private void UpdateReferences(Project project, ImmutableArray<string> projectRef
{
if (_projectFiles.TryGetValue(project.FilePath, out var projectFileInfo))
{
if (projectFileInfo.ReferenceAliases != null && projectFileInfo.ReferenceAliases.TryGetValue(referencePath, out var aliases))
if (projectFileInfo.ReferenceAliases.TryGetValue(referencePath, out var aliases))
{
if (!string.IsNullOrEmpty(aliases))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../ExternAlias.Lib/ExternAlias.Lib.csproj">
<!-- do not reference by ProjectReference for reference with alias -->
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<Reference Include="ExternAlias.Lib">
<HintPath>$(ProjectDir)../ExternAlias.Lib/bin/$(Configuration)/netstandard2.0/ExternAlias.Lib.dll</HintPath>
<Aliases>abc</Aliases>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>ExternAlias.App</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../ExternAlias.Lib/ExternAlias.Lib.csproj">
<Aliases>abc</Aliases>
</ProjectReference>
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions test-assets/test-projects/ExternAlias/ExternAlias.App2/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
extern alias abc;
using System;

namespace ExternAlias.App
{
class Program
{
static void Main(string[] args)
{
new abc::ExternAlias.Lib.Class1();
Console.WriteLine("Hello World!");
}
}
}
14 changes: 14 additions & 0 deletions test-assets/test-projects/ExternAlias/ExternAlias.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternAlias.App", "ExternAl
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternAlias.Lib", "ExternAlias.Lib\ExternAlias.Lib.csproj", "{ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternAlias.App2", "ExternAlias.App2\ExternAlias.App2.csproj", "{220989D8-7529-4F49-BD49-8A256E6BC020}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -44,5 +46,17 @@ Global
{ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x64.Build.0 = Release|Any CPU
{ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x86.ActiveCfg = Release|Any CPU
{ECC29DFA-3AC0-474E-9C5C-C8AD4D3DD17D}.Release|x86.Build.0 = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|Any CPU.Build.0 = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|x64.ActiveCfg = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|x64.Build.0 = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|x86.ActiveCfg = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Debug|x86.Build.0 = Debug|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|Any CPU.ActiveCfg = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|Any CPU.Build.0 = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|x64.ActiveCfg = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|x64.Build.0 = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|x86.ActiveCfg = Release|Any CPU
{220989D8-7529-4F49-BD49-8A256E6BC020}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
28 changes: 24 additions & 4 deletions tests/OmniSharp.MSBuild.Tests/ProjectFileInfoTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public async Task CSharp8AndNullableContext_has_correct_property_values()
}

[Fact]
public async Task ExternAlias()
public async Task ExternAliasWithReference()
{
using (var host = CreateOmniSharpHost())
using (var testProject = await _testAssets.GetTestProjectAsync("ExternAlias"))
Expand All @@ -152,15 +152,35 @@ public async Task ExternAlias()
Assert.Single(projectFileInfo.ReferenceAliases);
foreach(var kv in projectFileInfo.ReferenceAliases)
{
this.TestOutput.WriteLine($"{kv.Key} = {kv.Value}");
TestOutput.WriteLine($"{kv.Key} = {kv.Value}");
}
// reference path should be same as evaluated HintPath("$(ProjectDir)../ExternAlias.Lib/bin/Debug/netstandard2.0/ExternAlias.Lib.dll")
var libpath = string.Format($"{Path.Combine(testProject.Directory, "ExternAlias.App")}{Path.DirectorySeparatorChar}../ExternAlias.Lib/bin/Debug/netstandard2.0/ExternAlias.Lib.dll");

var libpath = Path.Combine(testProject.Directory, "ExternAlias.Lib", "bin", "Debug", "netstandard2.0", "ExternAlias.Lib.dll");
Assert.True(projectFileInfo.ReferenceAliases.ContainsKey(libpath));
Assert.Equal("abc", projectFileInfo.ReferenceAliases[libpath]);
}
}

[Fact]
public async Task ExternAliasWithProjectReference()
{
using (var host = CreateOmniSharpHost())
using (var testProject = await _testAssets.GetTestProjectAsync("ExternAlias"))
{
var projectFilePath = Path.Combine(testProject.Directory, "ExternAlias.App2", "ExternAlias.App2.csproj");
var projectFileInfo = CreateProjectFileInfo(host, testProject, projectFilePath);
Assert.Single(projectFileInfo.ProjectReferenceAliases);
foreach(var kv in projectFileInfo.ProjectReferenceAliases)
{
TestOutput.WriteLine($"{kv.Key} = {kv.Value}");
}

var projectReferencePath = Path.Combine(testProject.Directory, "ExternAlias.Lib", "ExternAlias.Lib.csproj");
Assert.True(projectFileInfo.ProjectReferenceAliases.ContainsKey(projectReferencePath));
Assert.Equal("abc", projectFileInfo.ProjectReferenceAliases[projectReferencePath]);
}
}

[Fact]
public async Task AllowUnsafe()
{
Expand Down
47 changes: 47 additions & 0 deletions tests/OmniSharp.MSBuild.Tests/WorkspaceInformationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using TestUtility;
using Xunit;
Expand Down Expand Up @@ -272,5 +273,51 @@ public async Task DoesntParticipateInWorkspaceInfoResponseWhenDisabled()
Assert.Null(workspaceInfo);
}
}

[Fact]
public async Task TestProjectWithAliasOnProjectReference()
{
using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ExternAlias"))
using (var host = CreateMSBuildTestHost(testProject.Directory))
{
var project = host
.Workspace
.CurrentSolution
.Projects
.Single(x => x.AssemblyName == "ExternAlias.App2");

var lib = host
.Workspace
.CurrentSolution
.Projects
.Single(x => x.AssemblyName == "ExternAlias.Lib");

var projectReference = project
.ProjectReferences
.Single(x => x.ProjectId == lib.Id);

Assert.Equal("abc", projectReference.Aliases.Single());
}
}

[Fact]
public async Task TestProjectWithAliasOnReference()
{
using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ExternAlias"))
using (var host = CreateMSBuildTestHost(testProject.Directory))
{
var project = host
.Workspace
.CurrentSolution
.Projects
.Single(x => x.AssemblyName == "ExternAlias.App");

var reference = project
.MetadataReferences
.Single(x => x.Display == "ExternAlias.Lib.dll");

Assert.Equal("abc", reference.Properties.Aliases.Single());
}
}
}
}