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

Simpler fix for FUTD check of copy items when building for debug #9133

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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 @@ -151,12 +151,13 @@ private static bool IsBuild(uint options, out bool isRebuild)
return null;
}

int IVsUpdateSolutionEvents.UpdateSolution_StartUpdate(ref int pfCancelUpdate)
int IVsUpdateSolutionEvents.UpdateSolution_Begin(ref int pfCancelUpdate)
{
_solutionBuildEventListener.NotifySolutionBuildStarting();

return HResult.OK;
}

int IVsUpdateSolutionEvents.UpdateSolution_Done(int fSucceeded, int fModified, int fCancelCommand)
{
_solutionBuildEventListener.NotifySolutionBuildCompleted(cancelled: false);
Expand All @@ -174,7 +175,7 @@ int IVsUpdateSolutionEvents.UpdateSolution_Cancel()
#region IVsUpdateSolutionEvents stubs

int IVsUpdateSolutionEvents.OnActiveProjectCfgChange(IVsHierarchy pIVsHierarchy) => HResult.OK;
int IVsUpdateSolutionEvents.UpdateSolution_Begin(ref int pfCancelUpdate) => HResult.OK;
int IVsUpdateSolutionEvents.UpdateSolution_StartUpdate(ref int pfCancelUpdate) => HResult.OK;

int IVsUpdateSolutionEvents2.OnActiveProjectCfgChange(IVsHierarchy pIVsHierarchy) => HResult.OK;
int IVsUpdateSolutionEvents2.UpdateSolution_Begin(ref int pfCancelUpdate) => HResult.OK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.VisualStudio.ProjectSystem.UpToDate
{
internal sealed partial class BuildUpToDateCheck
{
internal readonly struct TimestampCache
internal readonly struct TimestampCache : ITimestampCache
{
private readonly Dictionary<string, DateTime> _timestampCache = new(StringComparers.Paths);
private readonly IFileSystem _fileSystem;
Expand Down Expand Up @@ -42,6 +42,12 @@ public TimestampCache(IFileSystem fileSystem)

return time;
}

public void ClearTimestamps(IEnumerable<string> paths)
{
// This should never be called.
throw new NotImplementedException();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -722,12 +722,8 @@ private bool CheckBuiltFromInputFiles(Log log, in TimestampCache timestampCache,
return true;
}

private bool CheckCopyToOutputDirectoryItems(Log log, UpToDateCheckImplicitConfiguredInput state, IEnumerable<(string Path, ImmutableArray<CopyItem> CopyItems)> copyItemsByProject, ConfiguredFileSystemOperationAggregator fileSystemAggregator, bool? isBuildAccelerationEnabled, CancellationToken token)
private bool CheckCopyToOutputDirectoryItems(Log log, UpToDateCheckImplicitConfiguredInput state, IEnumerable<(string Path, ImmutableArray<CopyItem> CopyItems)> copyItemsByProject, ConfiguredFileSystemOperationAggregator fileSystemAggregator, ITimestampCache copyItemTimestampCache, bool? isBuildAccelerationEnabled, CancellationToken token)
{
ITimestampCache? timestampCache = _solutionBuildContextProvider.CurrentSolutionBuildContext?.CopyItemTimestamps;

Assumes.NotNull(timestampCache);

string outputFullPath = Path.Combine(state.MSBuildProjectDirectory, state.OutputRelativeOrFullPath);

Log.Scope? scope1 = null;
Expand Down Expand Up @@ -771,7 +767,7 @@ private bool CheckCopyToOutputDirectoryItems(Log log, UpToDateCheckImplicitConfi

log.Verbose(nameof(Resources.FUTD_CheckingCopyToOutputDirectoryItem_1), copyType.ToString());

DateTime? sourceTime = timestampCache.GetTimestampUtc(sourcePath);
DateTime? sourceTime = copyItemTimestampCache.GetTimestampUtc(sourcePath);

if (sourceTime is null)
{
Expand All @@ -784,7 +780,7 @@ private bool CheckCopyToOutputDirectoryItems(Log log, UpToDateCheckImplicitConfi

log.Verbose(nameof(Resources.FUTD_SourceFileTimeAndPath_2), sourceTime, sourcePath);

DateTime? destinationTime = timestampCache.GetTimestampUtc(destinationPath);
DateTime? destinationTime = copyItemTimestampCache.GetTimestampUtc(destinationPath);

if (destinationTime is null)
{
Expand Down Expand Up @@ -958,26 +954,15 @@ private async Task<bool> IsUpToDateInternalAsync(
token.ThrowIfCancellationRequested();

// Short-lived cache of timestamp by path
var timestampCache = new TimestampCache(_fileSystem);
TimestampCache timestampCache = new(_fileSystem);

// Ensure we have a context object for the current solution build.
//
// Ordinarily, this is created when the SBM calls ISolutionBuildEventListener.NotifySolutionBuildStarting,
// and cleared again later when the SBM calls ISolutionBuildEventListener.NotifySolutionBuildCompleted.
//
// However there are two cases where it may be null here:
//
// 1. When performing a validation run that continues after the solution build completed, or
// 2. When the build occurs in response to debugging (e.g. F5) in which case the SBM calls the
// FUTDC *before* it invokes any solution build events.
//
// In either case, we construct an event here lazily so that we can correctly test for the
// existence of copy items in CheckCopyToOutputDirectoryItems.
if (_solutionBuildContextProvider.CurrentSolutionBuildContext is null)
{
_solutionBuildEventListener.NotifySolutionBuildStarting();
Assumes.NotNull(_solutionBuildContextProvider.CurrentSolutionBuildContext);
}
// For copy items, we share a timestamp cache across the solution build.
// It's constructed when the SBM calls IVsUpdateSolutionEvents.UpdateSolution_Begin,
// and cleared when the SBM calls IVsUpdateSolutionEvents.UpdateSolution_Done.
// If the FUTDC is called outside those events, the CurrentSolutionBuildContext will
// be null, so we share the same short-lived cache. This can happen when performing
// validation runs, which can occur after the solution build has completed.
ITimestampCache copyItemTimestampCache = _solutionBuildContextProvider.CurrentSolutionBuildContext?.CopyItemTimestamps ?? timestampCache;

globalProperties.TryGetValue(FastUpToDateCheckIgnoresKindsGlobalPropertyName, out string? ignoreKindsString);

Expand Down Expand Up @@ -1083,7 +1068,7 @@ private async Task<bool> IsUpToDateInternalAsync(
!CheckInputsAndOutputs(logger, lastSuccessfulBuildStartTimeUtc, timestampCache, implicitState, ignoreKinds, token) ||
!CheckBuiltFromInputFiles(logger, timestampCache, implicitState, token) ||
!CheckMarkers(logger, timestampCache, implicitState, isBuildAccelerationEnabled, fileSystemOperations) ||
!CheckCopyToOutputDirectoryItems(logger, implicitState, copyInfo.ItemsByProject, configuredFileSystemOperations, isBuildAccelerationEnabled, token))
!CheckCopyToOutputDirectoryItems(logger, implicitState, copyInfo.ItemsByProject, configuredFileSystemOperations, copyItemTimestampCache, isBuildAccelerationEnabled, token))
{
return (false, checkedConfigurations);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace Microsoft.VisualStudio.ProjectSystem.UpToDate;
/// </summary>
internal sealed class SolutionBuildContext
{

/// <summary>
/// A cache of timestamps for the absolute paths of both source and target of copy items
/// across all projects.
Expand Down
Loading