Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public async Task OpenSolutionAsync(string solutionFilePath)
_logger.LogInformation(string.Format(LanguageServerResources.Loading_0, solutionFilePath));
ProjectFactory.SolutionPath = solutionFilePath;

var (_, projects) = await SolutionFileReader.ReadSolutionFileAsync(solutionFilePath, CancellationToken.None);
var (_, projects) = await SolutionFileReader.ReadSolutionFileAsync(solutionFilePath, DiagnosticReportingMode.Throw, CancellationToken.None);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want something else here or are we going to throw exceptions and not load a solution that we could mostly load? (this question is not blocking considering the regression you're fixing here)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this generally matches prior behavior, but I'll do some tests to see if we can relax it and load slns with potentially invalid projects. Will followup.

foreach (var (path, guid) in projects)
{
await BeginLoadingProjectAsync(path, guid);
Expand Down
14 changes: 7 additions & 7 deletions src/Workspaces/MSBuild/Core/MSBuild/MSBuildProjectLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,20 @@ public async Task<SolutionInfo> LoadSolutionInfoAsync(
throw new ArgumentNullException(nameof(solutionFilePath));
}

var (absoluteSolutionPath, projects) = await SolutionFileReader.ReadSolutionFileAsync(solutionFilePath, _pathResolver, cancellationToken).ConfigureAwait(false);
var reportingMode = GetReportingModeForUnrecognizedProjects();

var reportingOptions = new DiagnosticReportingOptions(
onPathFailure: reportingMode,
onLoaderFailure: reportingMode);

var (absoluteSolutionPath, projects) = await SolutionFileReader.ReadSolutionFileAsync(solutionFilePath, _pathResolver, reportingMode, cancellationToken).ConfigureAwait(false);
var projectPaths = projects.SelectAsArray(p => p.ProjectPath);

using (_dataGuard.DisposableWait(cancellationToken))
{
SetSolutionProperties(absoluteSolutionPath);
}

var reportingMode = GetReportingModeForUnrecognizedProjects();

var reportingOptions = new DiagnosticReportingOptions(
onPathFailure: reportingMode,
onLoaderFailure: reportingMode);

var buildHostProcessManager = new BuildHostProcessManager(Properties, loggerFactory: _loggerFactory);
await using var _ = buildHostProcessManager.ConfigureAwait(false);

Expand Down
30 changes: 17 additions & 13 deletions src/Workspaces/MSBuild/Core/MSBuild/SolutionFileReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

Expand All @@ -14,12 +14,12 @@ namespace Microsoft.CodeAnalysis.MSBuild;

internal partial class SolutionFileReader
{
public static Task<(string AbsoluteSolutionPath, ImmutableArray<(string ProjectPath, string ProjectGuid)> Projects)> ReadSolutionFileAsync(string solutionFilePath, CancellationToken cancellationToken)
public static Task<(string AbsoluteSolutionPath, ImmutableArray<(string ProjectPath, string ProjectGuid)> Projects)> ReadSolutionFileAsync(string solutionFilePath, DiagnosticReportingMode diagnosticReportingMode, CancellationToken cancellationToken)
{
return ReadSolutionFileAsync(solutionFilePath, new PathResolver(diagnosticReporter: null), cancellationToken);
return ReadSolutionFileAsync(solutionFilePath, new PathResolver(diagnosticReporter: null), diagnosticReportingMode, cancellationToken);
}

public static async Task<(string AbsoluteSolutionPath, ImmutableArray<(string ProjectPath, string ProjectGuid)> Projects)> ReadSolutionFileAsync(string solutionFilePath, PathResolver pathResolver, CancellationToken cancellationToken)
public static async Task<(string AbsoluteSolutionPath, ImmutableArray<(string ProjectPath, string ProjectGuid)> Projects)> ReadSolutionFileAsync(string solutionFilePath, PathResolver pathResolver, DiagnosticReportingMode diagnosticReportingMode, CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(pathResolver.TryGetAbsoluteSolutionPath(solutionFilePath, baseDirectory: Directory.GetCurrentDirectory(), DiagnosticReportingMode.Throw, out var absoluteSolutionPath));

Expand All @@ -31,7 +31,7 @@ internal partial class SolutionFileReader
throw new Exception(string.Format(WorkspaceMSBuildResources.Failed_to_load_solution_filter_0, solutionFilePath));
}

var projects = await TryReadSolutionFileAsync(absoluteSolutionPath, pathResolver, projectFilter, cancellationToken).ConfigureAwait(false);
var projects = await TryReadSolutionFileAsync(absoluteSolutionPath, pathResolver, projectFilter, diagnosticReportingMode, cancellationToken).ConfigureAwait(false);
if (!projects.HasValue)
{
throw new Exception(string.Format(WorkspaceMSBuildResources.Failed_to_load_solution_0, absoluteSolutionPath));
Expand All @@ -40,7 +40,7 @@ internal partial class SolutionFileReader
return (absoluteSolutionPath, projects.Value);
}

private static async Task<ImmutableArray<(string ProjectPath, string ProjectGuid)>?> TryReadSolutionFileAsync(string solutionFilePath, PathResolver pathResolver, ImmutableHashSet<string> projectFilter, CancellationToken cancellationToken)
private static async Task<ImmutableArray<(string ProjectPath, string ProjectGuid)>?> TryReadSolutionFileAsync(string solutionFilePath, PathResolver pathResolver, ImmutableHashSet<string> projectFilter, DiagnosticReportingMode diagnosticReportingMode, CancellationToken cancellationToken)
{
var serializer = SolutionSerializers.GetSerializerByMoniker(solutionFilePath);
if (serializer == null)
Expand All @@ -57,17 +57,21 @@ internal partial class SolutionFileReader
var builder = ImmutableArray.CreateBuilder<(string ProjectPath, string ProjectGuid)>();
foreach (var projectModel in solutionModel.SolutionProjects)
{
// If we are filtering based on a solution filter, then we need to verify the project is included.
if (!projectFilter.IsEmpty)
// If we didn't get an absolute path skip the file. The solution may have an invalid project in it,
// but we don't want to throw on that here. The path resolver will throw / report a diagnostic if it couldn't resolve the path.
if (pathResolver.TryGetAbsoluteProjectPath(projectModel.FilePath, baseDirectory, diagnosticReportingMode, out var absoluteProjectPath))
{
Contract.ThrowIfFalse(pathResolver.TryGetAbsoluteProjectPath(projectModel.FilePath, baseDirectory, DiagnosticReportingMode.Throw, out var absoluteProjectPath));
if (!projectFilter.Contains(absoluteProjectPath))
// If we are filtering based on a solution filter, then we need to verify the project is included.
if (!projectFilter.IsEmpty)
{
continue;
if (!projectFilter.Contains(absoluteProjectPath))
{
continue;
}
}
}

builder.Add((projectModel.FilePath, projectModel.Id.ToString()));
builder.Add((absoluteProjectPath, projectModel.Id.ToString()));
}
}

return builder.ToImmutable();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ConsoleApplication2", "ConsoleApplication2\ConsoleApplication2.vbproj", "{378156D6-840C-47CC-A465-639548363FF7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpProject", "CSharpProject\CSharpProject.csproj", "{686DD036-86AA-443E-8A10-DDB43266A8C4}"
EndProject

# Comment to test the handling of the parsing of .sln file with comments b/n project block
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.csproj", "{BF7B38CE-F5CA-4467-A3CF-D1796CE2BAC0}"
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "VisualBasicProject", "VisualBasicProject\VisualBasicProject.vbproj", "{AC25ECDA-DE94-4FCF-A688-EB3A2BE3670C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{378156D6-840C-47CC-A465-639548363FF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{378156D6-840C-47CC-A465-639548363FF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{378156D6-840C-47CC-A465-639548363FF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{378156D6-840C-47CC-A465-639548363FF7}.Release|Any CPU.Build.0 = Release|Any CPU
{BF7B38CE-F5CA-4467-A3CF-D1796CE2BAC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF7B38CE-F5CA-4467-A3CF-D1796CE2BAC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF7B38CE-F5CA-4467-A3CF-D1796CE2BAC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF7B38CE-F5CA-4467-A3CF-D1796CE2BAC0}.Release|Any CPU.Build.0 = Release|Any CPU
{686DD036-86AA-443E-8A10-DDB43266A8C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{686DD036-86AA-443E-8A10-DDB43266A8C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{686DD036-86AA-443E-8A10-DDB43266A8C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{686DD036-86AA-443E-8A10-DDB43266A8C4}.Release|Any CPU.Build.0 = Release|Any CPU
{AC25ECDA-DE94-4FCF-A688-EB3A2BE3670C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC25ECDA-DE94-4FCF-A688-EB3A2BE3670C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC25ECDA-DE94-4FCF-A688-EB3A2BE3670C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC25ECDA-DE94-4FCF-A688-EB3A2BE3670C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1002,13 +1002,11 @@ public async Task TestOpenSolution_WithLockedFile_LoadsWithEmptyText()
public async Task TestOpenSolution_WithInvalidProjectPath_SkipTrue_SucceedsWithFailureEvent()
{
// when skipped we should see a diagnostic for the invalid project
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the test was never testing what it claimed to test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It kind of was. But it was setting the wrong flag to allow it to create the diagnostic


CreateFiles(GetSimpleCSharpSolutionFiles()
.WithFile(@"TestSolution.sln", Resources.SolutionFiles.InvalidProjectPath));

var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");
CreateFiles(GetSimpleCSharpProjectFiles()
.WithFile(solutionFilePath, Resources.SolutionFiles.InvalidProjectPath));

using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false, skipUnrecognizedProjects: true);
var solution = await workspace.OpenSolutionAsync(solutionFilePath);
Assert.Single(workspace.Diagnostics);
}
Expand Down Expand Up @@ -1050,7 +1048,7 @@ public async Task TestOpenSolution_WithNonExistentProject_SkipTrue_SucceedsWithF
.WithFile(@"TestSolution.sln", Resources.SolutionFiles.NonExistentProject));
var solutionFilePath = GetSolutionFileName(@"TestSolution.sln");

using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false, skipUnrecognizedProjects: true);
var solution = await workspace.OpenSolutionAsync(solutionFilePath);

Assert.Single(workspace.Diagnostics);
Expand Down Expand Up @@ -2653,11 +2651,12 @@ public async Task TestOpenSolution_SolutionFileHasEmptyLinesAndWhitespaceOnlyLin
[WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531543")]
public async Task TestOpenSolution_SolutionFileHasEmptyLineBetweenProjectBlock()
{
var files = new FileSet(
(@"TestSolution.sln", Resources.SolutionFiles.EmptyLineBetweenProjectBlock));
var solutionFilePath = GetSolutionFileName("TestSolution.sln");
var files = GetSimpleCSharpProjectFiles()
.Concat(GetSimpleVisualBasicProjectFiles())
.Concat([(solutionFilePath, Resources.SolutionFiles.EmptyLineBetweenProjectBlock)]);

CreateFiles(files);
var solutionFilePath = GetSolutionFileName("TestSolution.sln");

using var workspace = CreateMSBuildWorkspace(throwOnWorkspaceFailed: false);
var solution = await workspace.OpenSolutionAsync(solutionFilePath);
Expand Down
13 changes: 11 additions & 2 deletions src/Workspaces/MSBuild/Test/WorkspaceTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.UnitTests.TestFiles;
using Roslyn.Test.Utilities;
Expand Down Expand Up @@ -84,18 +85,26 @@ protected void CreateCSharpFiles()
}

protected static FileSet GetSimpleCSharpSolutionFiles()
{
return GetSimpleCSharpProjectFiles().WithFile(@"TestSolution.sln", Resources.SolutionFiles.CSharp);
}

protected static FileSet GetSimpleCSharpProjectFiles()
{
return new FileSet(
(@"TestSolution.sln", Resources.SolutionFiles.CSharp),
(@"CSharpProject\CSharpProject.csproj", Resources.ProjectFiles.CSharp.CSharpProject),
(@"CSharpProject\CSharpClass.cs", Resources.SourceFiles.CSharp.CSharpClass),
(@"CSharpProject\Properties\AssemblyInfo.cs", Resources.SourceFiles.CSharp.AssemblyInfo));
}

protected static FileSet GetSimpleVisualBasicSolutionFiles()
{
return GetSimpleVisualBasicProjectFiles().WithFile(@"TestSolution.sln", Resources.SolutionFiles.VisualBasic);
}

protected static FileSet GetSimpleVisualBasicProjectFiles()
{
return new FileSet(
(@"TestSolution.sln", Resources.SolutionFiles.VisualBasic),
(@"VisualBasicProject\VisualBasicProject.vbproj", Resources.ProjectFiles.VisualBasic.VisualBasicProject),
(@"VisualBasicProject\VisualBasicClass.vb", Resources.SourceFiles.VisualBasic.VisualBasicClass),
(@"VisualBasicProject\My Project\Application.Designer.vb", Resources.SourceFiles.VisualBasic.Application_Designer),
Expand Down
Loading