Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/vs15.9' into RIvs15.9
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyGerlicher committed Aug 16, 2018
2 parents 6f7b538 + 0a5001f commit 6d83837
Show file tree
Hide file tree
Showing 16 changed files with 95 additions and 32 deletions.
Expand Up @@ -455,6 +455,7 @@ public abstract partial class SdkResolver
public abstract partial class SdkResolverContext
{
protected SdkResolverContext() { }
public virtual bool Interactive { get { throw null; } protected set { } }
public virtual Microsoft.Build.Framework.SdkLogger Logger { get { throw null; } protected set { } }
public virtual System.Version MSBuildVersion { get { throw null; } protected set { } }
public virtual string ProjectFilePath { get { throw null; } protected set { } }
Expand Down
Expand Up @@ -454,6 +454,7 @@ public abstract partial class SdkResolver
public abstract partial class SdkResolverContext
{
protected SdkResolverContext() { }
public virtual bool Interactive { get { throw null; } protected set { } }
public virtual Microsoft.Build.Framework.SdkLogger Logger { get { throw null; } protected set { } }
public virtual System.Version MSBuildVersion { get { throw null; } protected set { } }
public virtual string ProjectFilePath { get { throw null; } protected set { } }
Expand Down
2 changes: 1 addition & 1 deletion src/Build.UnitTests/BackEnd/MockSdkResolverService.cs
Expand Up @@ -19,7 +19,7 @@ public void ClearCaches()
{
}

public Build.BackEnd.SdkResolution.SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
public Build.BackEnd.SdkResolution.SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
{
return null;
}
Expand Down
54 changes: 43 additions & 11 deletions src/Build.UnitTests/BackEnd/SdkResolverService_Tests.cs
Expand Up @@ -40,7 +40,7 @@ public void AssertAllResolverErrorsLoggedWhenSdkNotResolved()

SdkReference sdk = new SdkReference("notfound", "referencedVersion", "minimumVersion");

var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);

result.Success.ShouldBeFalse();
result.ShouldNotBeNull();
Expand Down Expand Up @@ -73,7 +73,7 @@ public void AssertResolutionWarnsIfResolvedVersionIsDifferentFromReferencedVersi
))
});

var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);

result.Path.ShouldBe("path");

Expand All @@ -88,7 +88,7 @@ public void AssertErrorLoggedWhenResolverThrows()

SdkReference sdk = new SdkReference("1sdkName", "version1", "minimumVersion");

var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);

result.Path.ShouldBe("resolverpath1");
_logger.Warnings.Select(i => i.Message).ShouldBe(new [] { "The SDK resolver \"MockSdkResolverThrows\" failed to run. EXMESSAGE" });
Expand All @@ -101,7 +101,7 @@ public void AssertFirstResolverCanResolve()

SdkReference sdk = new SdkReference("1sdkName", "referencedVersion", "minimumVersion");

var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);

result.Path.ShouldBe("resolverpath1");
_logger.BuildMessageEvents.Select(i => i.Message).ShouldContain("MockSdkResolver1 running");
Expand All @@ -116,7 +116,7 @@ public void AssertFirstResolverErrorsSupressedWhenResolved()
// be logged because MockSdkResolver2 will succeed.
SdkReference sdk = new SdkReference("2sdkName", "version2", "minimumVersion");

var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = SdkResolverService.Instance.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);

result.Path.ShouldBe("resolverpath2");

Expand All @@ -139,10 +139,10 @@ public void AssertResolverHasStatePreserved()
SdkReference sdk = new SdkReference("othersdk", "1.0", "minimumVersion");

// First call should not know state
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath").Path.ShouldBe("resolverpath");
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false).Path.ShouldBe("resolverpath");

// Second call should have received state
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath").Path.ShouldBe(MockSdkResolverWithState.Expected);
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false).Path.ShouldBe(MockSdkResolverWithState.Expected);
}

[Fact]
Expand All @@ -155,10 +155,10 @@ public void AssertResolverStateNotPreserved()
SdkReference sdk = new SdkReference("othersdk", "1.0", "minimumVersion");

// First call should not know state
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath").Path.ShouldBe("resolverpath");
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false).Path.ShouldBe("resolverpath");

// Second call should have received state
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath").Path.ShouldBe("resolverpath");
SdkResolverService.Instance.ResolveSdk(submissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false).Path.ShouldBe("resolverpath");
}

[Theory]
Expand Down Expand Up @@ -199,13 +199,13 @@ public void CachingWrapperShouldWarnWhenMultipleVersionsAreReferenced()
resolver
});

var result = service.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
var result = service.ResolveSdk(BuildEventContext.InvalidSubmissionId, sdk, _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);
resolver.ResolvedCalls.Count.ShouldBe(1);
result.Path.ShouldBe("path");
result.Version.ShouldBe("1.0.0");
_logger.WarningCount.ShouldBe(0);

result = service.ResolveSdk(BuildEventContext.InvalidSubmissionId, new SdkReference("foo", "2.0.0", null), _loggingContext, new MockElementLocation("file"), "sln", "projectPath");
result = service.ResolveSdk(BuildEventContext.InvalidSubmissionId, new SdkReference("foo", "2.0.0", null), _loggingContext, new MockElementLocation("file"), "sln", "projectPath", interactive: false);
resolver.ResolvedCalls.Count.ShouldBe(1);
result.Path.ShouldBe("path");
result.Version.ShouldBe("1.0.0");
Expand All @@ -216,6 +216,38 @@ public void CachingWrapperShouldWarnWhenMultipleVersionsAreReferenced()
resolver.ResolvedCalls.Count.ShouldBe(1);
}

[Fact]
public void InteractiveIsSetForResolverContext()
{
// Start with interactive false
bool interactive = false;

var service = new CachingSdkResolverService();

service.InitializeForTests(
resolvers: new List<SdkResolver>
{
new SdkUtilities.ConfigurableMockSdkResolver((sdkRference, resolverContext, factory) =>
{
interactive = resolverContext.Interactive;
return null;
})
});

service.ResolveSdk(
BuildEventContext.InvalidSubmissionId,
new SdkReference("foo", "1.0.0", null),
_loggingContext,
new MockElementLocation("file"),
"sln",
"projectPath",
// Pass along interactive and expect it to be received in the SdkResolverContext
interactive: true);

interactive.ShouldBeTrue();
}

private class MockLoaderStrategy : SdkResolverLoader
{
private readonly bool _includeErrorResolver;
Expand Down
13 changes: 13 additions & 0 deletions src/Build.UnitTests/InternalEngineHelpers.cs
Expand Up @@ -35,6 +35,7 @@ public static ProjectOptions CreateProjectOptionsWithResolver(SdkResolver resolv
internal class ConfigurableMockSdkResolver : SdkResolver
{
private readonly Dictionary<string, SdkResult> _resultMap;
private readonly Func<SdkReference, SdkResolverContext, SdkResultFactory, Framework.SdkResult> _resolveFunc;

public ConcurrentDictionary<string, int> ResolvedCalls { get; } = new ConcurrentDictionary<string, int>();

Expand All @@ -48,18 +49,30 @@ public ConfigurableMockSdkResolver(Dictionary<string, SdkResult> resultMap)
_resultMap = resultMap;
}

public ConfigurableMockSdkResolver(Func<SdkReference, SdkResolverContext, SdkResultFactory, Framework.SdkResult> resolveFunc)
{
_resolveFunc = resolveFunc;
}

public override string Name => nameof(ConfigurableMockSdkResolver);

public override int Priority => int.MaxValue;

public override Framework.SdkResult Resolve(SdkReference sdkReference, SdkResolverContext resolverContext, SdkResultFactory factory)
{
if (_resolveFunc != null)
{
return _resolveFunc(sdkReference, resolverContext, factory);
}

ResolvedCalls.AddOrUpdate(sdkReference.Name, k => 1, (k, c) => c + 1);

return _resultMap.TryGetValue(sdkReference.Name, out var result)
? new SdkResult(sdkReference, result.Path, result.Version, null)
: null;
}


}

internal class FileBasedMockSdkResolver : SdkResolver
Expand Down
Expand Up @@ -33,13 +33,13 @@ public override void ClearCaches()
_cache.Clear();
}

public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
{
SdkResult result;

if (Traits.Instance.EscapeHatches.DisableSdkResolutionCache)
{
result = base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath);
result = base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath, interactive);
}
else
{
Expand All @@ -53,7 +53,7 @@ public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, Logging
*/
result = cached.GetOrAdd(
sdk.Name,
key => base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath));
key => base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath, interactive));
}

if (result != null &&
Expand Down
Expand Up @@ -47,7 +47,7 @@ public virtual void InitializeComponent(IBuildComponentHost host)
public abstract void PacketReceived(int node, INodePacket packet);

/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/>
public abstract SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath);
public abstract SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive);

/// <inheritdoc cref="IBuildComponent.ShutdownComponent"/>
public virtual void ShutdownComponent()
Expand Down
Expand Up @@ -38,7 +38,8 @@ internal interface ISdkResolverService
/// <param name="sdkReferenceLocation">The <see cref="ElementLocation"/> of the element which referenced the SDK.</param>
/// <param name="solutionPath">The full path to the solution file, if any, that is resolving the SDK.</param>
/// <param name="projectPath">The full path to the project file that is resolving the SDK.</param>
/// <param name="interactive">Indicates whether or not the resolver is allowed to be interactive.</param>
/// <returns>An <see cref="SdkResult"/> containing information about the resolved SDK. If no resolver was able to resolve it, then <see cref="Framework.SdkResult.Success"/> == false. </returns>
SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath);
SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive);
}
}
Expand Up @@ -81,14 +81,14 @@ public override void PacketReceived(int node, INodePacket packet)
}

/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/>
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
{
ErrorUtilities.VerifyThrowInternalNull(sdk, nameof(sdk));
ErrorUtilities.VerifyThrowInternalNull(loggingContext, nameof(loggingContext));
ErrorUtilities.VerifyThrowInternalNull(sdkReferenceLocation, nameof(sdkReferenceLocation));
ErrorUtilities.VerifyThrowInternalLength(projectPath, nameof(projectPath));

return _cachedSdkResolver.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath);
return _cachedSdkResolver.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath, interactive);
}

/// <summary>
Expand Down Expand Up @@ -155,7 +155,7 @@ private void ProcessRequests()
ILoggingService loggingService = Host.GetComponent(BuildComponentType.LoggingService) as ILoggingService;
// This call is usually cached so is very fast but can take longer for a new SDK that is downloaded. Other queued threads for different SDKs will complete sooner and continue on which unblocks evaluations
response = ResolveSdk(request.SubmissionId, sdkReference, new EvaluationLoggingContext(loggingService, request.BuildEventContext, request.ProjectPath), request.ElementLocation, request.SolutionPath, request.ProjectPath);
response = ResolveSdk(request.SubmissionId, sdkReference, new EvaluationLoggingContext(loggingService, request.BuildEventContext, request.ProjectPath), request.ElementLocation, request.SolutionPath, request.ProjectPath, request.Interactive);
}
catch (Exception e)
{
Expand Down
Expand Up @@ -61,14 +61,14 @@ public override void PacketReceived(int node, INodePacket packet)
}

/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/>
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
{
// Get a cached response if possible, otherwise send the request
var sdkResult = _responseCache.GetOrAdd(
sdk.Name,
key =>
{
var result = RequestSdkPathFromMainNode(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath);
var result = RequestSdkPathFromMainNode(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath, interactive);
return new SdkResult(null, result.Path, result.Version, null);
});

Expand Down Expand Up @@ -103,13 +103,13 @@ private void HandleResponse(SdkResult response)
_responseReceivedEvent.Set();
}

private SdkResult RequestSdkPathFromMainNode(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
private SdkResult RequestSdkPathFromMainNode(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
{
// Clear out the last response for good measure
_lastResponse = null;

// Create the SdkResolverRequest packet to send
INodePacket packet = SdkResolverRequest.Create(submissionId, sdk, loggingContext.BuildEventContext, sdkReferenceLocation, solutionPath, projectPath);
INodePacket packet = SdkResolverRequest.Create(submissionId, sdk, loggingContext.BuildEventContext, sdkReferenceLocation, solutionPath, projectPath, interactive);

SendPacket(packet);

Expand Down
Expand Up @@ -12,12 +12,13 @@ namespace Microsoft.Build.BackEnd.SdkResolution
/// </summary>
internal sealed class SdkResolverContext : SdkResolverContextBase
{
public SdkResolverContext(Framework.SdkLogger logger, string projectFilePath, string solutionPath, Version msBuildVersion)
public SdkResolverContext(Framework.SdkLogger logger, string projectFilePath, string solutionPath, Version msBuildVersion, bool interactive)
{
Logger = logger;
ProjectFilePath = projectFilePath;
SolutionFilePath = solutionPath;
MSBuildVersion = msBuildVersion;
Interactive = interactive;
}
}
}

0 comments on commit 6d83837

Please sign in to comment.