-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Closed
Description
// Each participating language service exports this interface.
public interface IEditAndContinueManagedModuleUpdateProvider
{
// Returns the kind of change made to the modules owned by the provider.
// The change is aggregated across all applicable modules:
// if one module has a rude edit and another one has valid change the resulting kind is
// ManagedModuleUpdateStatus.Blocked.
// If sourceFilePath is not null considers only modules whose compilation is affected by
// the specified source file, otherwise considers all modules owned by the provider.
Task<ManagedModuleUpdateStatus> GetStatusAsync(string sourceFilePath, CancallationToken cancellationToken);
// Returns an array of code changes (for each module owned by the provider) or
// empty array if there was no change or error. Errors are reported by the language service.
Task<ManagedModuleUpdates> GetManagedModuleUpdatesAsync(CancallationToken cancellationToken);
// Notifies the provider that changes to all modules have been successfully applied,
// except for modules listed in failures.
void CommitUpdates(ImmutableArray<ManagedModuleUpdateFailure> failures);
}
public readonly struct ManagedModuleUpdateFailure
{
public Guid ModuleId { get; }
public int ErrorCode { get; }
}
public readonly struct ManagedModuleUpdates
{
ManagedModuleUpdateStatus Status { get; }
// Empty if Status != Ready.
ImmutableArray<ManagedModuleUpdate> Updates { get; }
}
public enum ManagedModuleUpdateStatus
{
None, // No change made.
Ready, // All changes are valid, can be applied.
Blocked, // Some changes are invalid, can't continue.
}
public readonly struct ManagedModuleUpdate
{
public Guid ModuleId { get; }
// applied to PE file:
public ImmutableArray<byte> ILDelta { get; }
public ImmutableArray<byte> MetadataDelta { get; }
// applied to PDB
public ImmutableArray<byte> PdbDelta { get; }
public ImmutableArray<SequencePointsUpdate> SequencePoints { get; }
public ImmutableArray<int> UpdatedMethods { get; }
public ImmutableArray<ActiveStatementUpdate> ActiveStatements { get; }
public ImmutableArray<ExceptionRegionUpdate> ExceptionRegions { get; } // leave instructions remapping
}
public readonly struct ActiveStatementUpdate // corresponds to ENCPROG_ACTIVE_STATEMENT_REMAP
{
public Guid ThreadId { get; }
public int MethodToken { get; }
public int MethodVersion { get; }
public int ILOffset { get; }
public TextSpan NewSpan { get; }
}
public readonly struct ExceptionRegionUpdate // corresponds to ENCPROG_EXCEPTION_RANGE
{
public int MethodToken { get; }
public int MethodVersion { get; }
public TextSpan NewSpan { get; }
public int LineDelta { get; }
}
public readonly struct SequencePointsUpdate // replacement for FILEUPDATE
{
public string FileName { get; } // as stored in PDB
public ImmutableArray<SourceLineUpdate> LineUpdates { get; }
}
public readonly struct SourceLineUpdate
{
public int OldLine { get; }
public int NewLine { get; }
}In CEncMgr::ApplyCodeChangesInternal replace
if (Helpers::IsManagedENC(pCurrentProject))
{
if (HasManagedEditsReady(pCurrentProject))
{
projects[cModifiedProjects].m_project.Attach(pCurrentProject.Detach());
cModifiedProjects++;
continue;
}
}with
if (Helpers::IsManagedENC(pCurrentProject))
{
continue;
}and add after the the current project loop a call to managed code that does this:
var providers = mef import all IEditAndContinueManagedModuleUpdateProvider;
foreach (var provider in providers)
{
if (await provider.GetStatusAsync(cancellationToken) == ManagedModuleUpdateStatus.Blocked)
{
Return false;
}
}Replace
hr = RebuildManagedProjects(cModifiedProjects, projects.GetData(), &fHadCompilerError, &fENCModifiedModuleLoaded, &fENCNotSupported, result);with a call to managed code that does:
var providers = mef import all IEditAndContinueManagedModuleUpdateProvider;
var allUpdates = new List<ImmutableArray<ManagedModuleUpdate>>();
foreach (var provider in providers)
{
var updates = await provider.GetManagedModuleUpdatesAsync(cancellationToken);
if (updates.Any(u => u.Status == ManagedModuleUpdateStatus.Blocked))
{
Return false;
}
allUpdates.Add(updates);
}
var failures = new List<ManagedModuleUpdateFailure>();
foreach (var updates in allUpdates)
{
foreach (var update in updates)
{
var error = TryApplyUpdate(update);
if (error != S_OK)
{
failures.Add(new ManagedModuleUpdateFailure(update.ModuleId, error));
}
}
}
var failuresImmutable = failures.ToImmutable();
foreach (var provider in providers)
{
provider.CommitUpdates(failuresImmutable);
}
if (failedModules.Any())
{
return false;
}Corresponding VSO bug: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/662811