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
15 changes: 13 additions & 2 deletions src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3598,8 +3598,19 @@ internal override bool CompileMethods(
return true;
}

private protected override EmitBaseline MapToCompilation(CommonPEModuleBuilder moduleBeingBuilt)
=> EmitHelpers.MapToCompilation(this, (PEDeltaAssemblyBuilder)moduleBeingBuilt);
private protected override SymbolMatcher CreatePreviousToCurrentSourceAssemblyMatcher(
EmitBaseline previousGeneration,
SynthesizedTypeMaps otherSynthesizedTypes,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherSynthesizedMembers,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherDeletedMembers)
{
return new CSharpSymbolMatcher(
sourceAssembly: ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly,
SourceAssembly,
otherSynthesizedTypes,
otherSynthesizedMembers,
otherDeletedMembers);
}

private class DuplicateFilePathsVisitor : CSharpSymbolVisitor
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Emit.EditAndContinue;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Symbols;
using Roslyn.Utilities;
Expand All @@ -27,25 +26,31 @@ internal sealed class CSharpSymbolMatcher : SymbolMatcher
public CSharpSymbolMatcher(
SourceAssemblySymbol sourceAssembly,
SourceAssemblySymbol otherAssembly,
SynthesizedTypeMaps synthesizedTypes,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherSynthesizedMembers,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherDeletedMembers)
SynthesizedTypeMaps otherSynthesizedTypes,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherSynthesizedMembers,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherDeletedMembers)
{
_visitor = new Visitor(sourceAssembly, otherAssembly, synthesizedTypes, otherSynthesizedMembers, otherDeletedMembers, new DeepTranslator(otherAssembly.GetSpecialType(SpecialType.System_Object)));
_visitor = new Visitor(
sourceAssembly,
otherAssembly,
otherSynthesizedTypes,
otherSynthesizedMembers,
otherDeletedMembers,
new DeepTranslator(otherAssembly.GetSpecialType(SpecialType.System_Object)));
}

public CSharpSymbolMatcher(
SynthesizedTypeMaps synthesizedTypes,
SourceAssemblySymbol sourceAssembly,
PEAssemblySymbol otherAssembly)
PEAssemblySymbol otherAssembly,
SynthesizedTypeMaps otherSynthesizedTypes)
{
_visitor = new Visitor(
sourceAssembly,
otherAssembly,
synthesizedTypes,
otherSynthesizedMembers: null,
deepTranslator: null,
otherDeletedMembers: null);
otherSynthesizedTypes,
otherSynthesizedMembers: SpecializedCollections.EmptyReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>(),
otherDeletedMembers: SpecializedCollections.EmptyReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>(),
deepTranslator: null);
}

public override Cci.IDefinition? MapDefinition(Cci.IDefinition definition)
Expand Down Expand Up @@ -93,9 +98,12 @@ static bool isPrivateImplementationDetail(Cci.IDefinition definition)
internal bool TryGetAnonymousTypeValue(AnonymousTypeManager.AnonymousTypeOrDelegateTemplateSymbol template, out AnonymousTypeValue typeValue)
=> _visitor.TryGetAnonymousTypeValue(template, out typeValue);

protected override bool TryGetMatchingDelegateWithIndexedName(INamedTypeSymbolInternal delegateTemplate, ImmutableArray<AnonymousTypeValue> values, out AnonymousTypeValue match)
=> _visitor.TryGetMatchingDelegateWithIndexedName((AnonymousTypeManager.AnonymousDelegateTemplateSymbol)delegateTemplate, values, out match);

private sealed class Visitor : CSharpSymbolVisitor<Symbol?>
{
private readonly SynthesizedTypeMaps _synthesizedTypes;
private readonly SynthesizedTypeMaps _otherSynthesizedTypes;
private readonly SourceAssemblySymbol _sourceAssembly;

// metadata or source assembly:
Expand All @@ -105,9 +113,9 @@ private sealed class Visitor : CSharpSymbolVisitor<Symbol?>
/// Members that are not listed directly on their containing type or namespace symbol as they were synthesized in a lowering phase,
/// after the symbol has been created.
/// </summary>
private readonly IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? _otherSynthesizedMembers;
private readonly IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> _otherSynthesizedMembers;

private readonly IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? _otherDeletedMembers;
private readonly IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> _otherDeletedMembers;

private readonly SymbolComparer _comparer;
private readonly ConcurrentDictionary<Symbol, Symbol?> _matches = new(ReferenceEqualityComparer.Instance);
Expand All @@ -123,12 +131,12 @@ private sealed class Visitor : CSharpSymbolVisitor<Symbol?>
public Visitor(
SourceAssemblySymbol sourceAssembly,
AssemblySymbol otherAssembly,
SynthesizedTypeMaps synthesizedTypes,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherSynthesizedMembers,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherDeletedMembers,
SynthesizedTypeMaps otherSynthesizedTypes,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherSynthesizedMembers,
IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> otherDeletedMembers,
DeepTranslator? deepTranslator)
{
_synthesizedTypes = synthesizedTypes;
_otherSynthesizedTypes = otherSynthesizedTypes;
_sourceAssembly = sourceAssembly;
_otherAssembly = otherAssembly;
_otherSynthesizedMembers = otherSynthesizedMembers;
Expand Down Expand Up @@ -470,45 +478,44 @@ private CustomModifier VisitCustomModifier(CustomModifier modifier)
CSharpCustomModifier.CreateRequired(type);
}

internal bool TryGetAnonymousDelegateValue(AnonymousTypeManager.AnonymousDelegateTemplateSymbol delegateSymbol, out SynthesizedDelegateValue otherDelegateSymbol)
private bool TryGetAnonymousDelegateValue(AnonymousTypeManager.AnonymousDelegateTemplateSymbol delegateSymbol, out SynthesizedDelegateValue otherDelegateSymbol)
{
Debug.Assert((object)delegateSymbol.ContainingSymbol == (object)_sourceAssembly.GlobalNamespace);

var key = new SynthesizedDelegateKey(delegateSymbol.MetadataName);
return _synthesizedTypes.AnonymousDelegates.TryGetValue(key, out otherDelegateSymbol);
return _otherSynthesizedTypes.AnonymousDelegates.TryGetValue(key, out otherDelegateSymbol);
}

internal bool TryGetAnonymousTypeValue(AnonymousTypeManager.AnonymousTypeOrDelegateTemplateSymbol template, out AnonymousTypeValue otherType)
{
Debug.Assert((object)template.ContainingSymbol == (object)_sourceAssembly.GlobalNamespace);

if (template is AnonymousTypeManager.AnonymousTypeTemplateSymbol typeTemplate)
{
return _synthesizedTypes.AnonymousTypes.TryGetValue(typeTemplate.GetAnonymousTypeKey(), out otherType);
return _otherSynthesizedTypes.AnonymousTypes.TryGetValue(typeTemplate.GetAnonymousTypeKey(), out otherType);
}

var delegateTemplate = (AnonymousTypeManager.AnonymousDelegateTemplateSymbol)template;
Debug.Assert(delegateTemplate.DelegateInvokeMethod != null);

otherType = default;

var key = new AnonymousDelegateWithIndexedNamePartialKey(delegateTemplate.Arity, delegateTemplate.DelegateInvokeMethod.ParameterCount);
if (_synthesizedTypes.AnonymousDelegatesWithIndexedNames.TryGetValue(key, out var otherTypeCandidates))
return _otherSynthesizedTypes.AnonymousDelegatesWithIndexedNames.TryGetValue(key, out var otherTypeCandidates) &&
TryGetMatchingDelegateWithIndexedName(delegateTemplate, otherTypeCandidates, out otherType);
}

internal bool TryGetMatchingDelegateWithIndexedName(AnonymousTypeManager.AnonymousDelegateTemplateSymbol delegateTemplate, ImmutableArray<AnonymousTypeValue> values, out AnonymousTypeValue match)
{
foreach (var otherTypeCandidate in values)
{
// The key is partial (not unique). Find a matching Invoke method signature.
var otherDelegateType = (NamedTypeSymbol?)otherTypeCandidate.Type.GetInternalSymbol();
Debug.Assert(otherDelegateType is not null);

foreach (var otherTypeCandidate in otherTypeCandidates)
if (isCorrespondingAnonymousDelegate(delegateTemplate, otherDelegateType))
{
var otherDelegateType = (NamedTypeSymbol?)otherTypeCandidate.Type.GetInternalSymbol();
Debug.Assert(otherDelegateType is not null);

if (isCorrespondingAnonymousDelegate(delegateTemplate, otherDelegateType))
{
otherType = otherTypeCandidate;
return true;
}
match = otherTypeCandidate;
return true;
}
}

otherType = default;
match = default;
return false;

bool isCorrespondingAnonymousDelegate(NamedTypeSymbol type, NamedTypeSymbol otherType)
Expand All @@ -526,12 +533,12 @@ otherType.DelegateInvokeMethod is { } otherInvokeMethod &&
x.IsParamsArray == y.IsParamsArray &&
x.IsParamsCollection == y.IsParamsCollection) &&
isCorrespondingType(invokeMethod.ReturnTypeWithAnnotations, otherInvokeMethod.ReturnTypeWithAnnotations);
}

bool isCorrespondingType(TypeWithAnnotations type, TypeWithAnnotations expectedType)
{
var otherType = type.WithTypeAndModifiers((TypeSymbol?)this.Visit(type.Type), this.VisitCustomModifiers(type.CustomModifiers));
return otherType.Equals(expectedType, TypeCompareKind.CLRSignatureCompareOptions);
bool isCorrespondingType(TypeWithAnnotations type, TypeWithAnnotations expectedType)
{
var otherType = type.WithTypeAndModifiers((TypeSymbol?)this.Visit(type.Type), this.VisitCustomModifiers(type.CustomModifiers));
return otherType.Equals(expectedType, TypeCompareKind.CLRSignatureCompareOptions);
}
}
}

Expand Down Expand Up @@ -799,12 +806,12 @@ private IReadOnlyDictionary<string, ImmutableArray<ISymbolInternal>> GetAllEmitt
members.AddRange(((NamespaceSymbol)symbol).GetMembers());
}

if (_otherSynthesizedMembers != null && _otherSynthesizedMembers.TryGetValue(symbol, out var synthesizedMembers))
if (_otherSynthesizedMembers.TryGetValue(symbol, out var synthesizedMembers))
{
members.AddRange(synthesizedMembers);
}

if (_otherDeletedMembers?.TryGetValue(symbol, out var deletedMembers) == true)
if (_otherDeletedMembers.TryGetValue(symbol, out var deletedMembers))
{
members.AddRange(deletedMembers);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata;
Expand All @@ -15,7 +14,6 @@
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Emit
{
Expand Down Expand Up @@ -67,14 +65,14 @@ internal static EmitDifferenceResult EmitDifference(
var metadataAssembly = (PEAssemblySymbol)metadataDecoder.ModuleSymbol.ContainingAssembly;

var sourceToMetadata = new CSharpSymbolMatcher(
metadataSymbols.SynthesizedTypes,
sourceAssembly,
metadataAssembly);
sourceAssembly: sourceAssembly,
otherAssembly: metadataAssembly,
otherSynthesizedTypes: metadataSymbols.SynthesizedTypes);

var previousSourceToMetadata = new CSharpSymbolMatcher(
metadataSymbols.SynthesizedTypes,
previousSourceAssembly,
metadataAssembly);
sourceAssembly: previousSourceAssembly,
otherAssembly: metadataAssembly,
otherSynthesizedTypes: metadataSymbols.SynthesizedTypes);

CSharpSymbolMatcher? currentSourceToPreviousSource = null;
if (baseline.Ordinal > 0)
Expand All @@ -84,7 +82,7 @@ internal static EmitDifferenceResult EmitDifference(
currentSourceToPreviousSource = new CSharpSymbolMatcher(
sourceAssembly: sourceAssembly,
otherAssembly: previousSourceAssembly,
baseline.SynthesizedTypes,
otherSynthesizedTypes: baseline.SynthesizedTypes,
otherSynthesizedMembers: baseline.SynthesizedMembers,
otherDeletedMembers: baseline.DeletedMembers);
}
Expand Down Expand Up @@ -178,66 +176,5 @@ private static bool GetPredefinedHotReloadExceptionTypeConstructor(CSharpCompila

return false;
}

/// <summary>
/// Return a version of the baseline with all definitions mapped to this compilation.
/// Definitions from the initial generation, from metadata, are not mapped since
/// the initial generation is always included as metadata. That is, the symbols from
/// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced
/// by the corresponding symbols from the current compilation.
/// </summary>
internal static EmitBaseline MapToCompilation(
CSharpCompilation compilation,
PEDeltaAssemblyBuilder moduleBeingBuilt)
{
var previousGeneration = moduleBeingBuilt.PreviousGeneration;
RoslynDebug.Assert(previousGeneration.Compilation != compilation);

if (previousGeneration.Ordinal == 0)
{
// Initial generation, nothing to map. (Since the initial generation
// is always loaded from metadata in the context of the current
// compilation, there's no separate mapping step.)
return previousGeneration;
}

RoslynDebug.AssertNotNull(previousGeneration.Compilation);
RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder);
RoslynDebug.AssertNotNull(moduleBeingBuilt.EncSymbolChanges);

var synthesizedTypes = moduleBeingBuilt.GetSynthesizedTypes();
var currentSynthesizedMembers = moduleBeingBuilt.GetAllSynthesizedMembers();
var currentDeletedMembers = moduleBeingBuilt.EncSymbolChanges.DeletedMembers;

// Mapping from previous compilation to the current.
var previousSourceAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;

var matcher = new CSharpSymbolMatcher(
previousSourceAssembly,
compilation.SourceAssembly,
synthesizedTypes,
currentSynthesizedMembers,
currentDeletedMembers);

var mappedSynthesizedMembers = matcher.MapSynthesizedOrDeletedMembers(previousGeneration.SynthesizedMembers, currentSynthesizedMembers, isDeletedMemberMapping: false);

// Deleted members are mapped the same way as synthesized members, so we can just call the same method.
var mappedDeletedMembers = matcher.MapSynthesizedOrDeletedMembers(previousGeneration.DeletedMembers, currentDeletedMembers, isDeletedMemberMapping: true);

// TODO: can we reuse some data from the previous matcher?
var matcherWithAllSynthesizedMembers = new CSharpSymbolMatcher(
previousSourceAssembly,
compilation.SourceAssembly,
synthesizedTypes,
mappedSynthesizedMembers,
mappedDeletedMembers);

return matcherWithAllSynthesizedMembers.MapBaselineToCompilation(
previousGeneration,
compilation,
moduleBeingBuilt,
mappedSynthesizedMembers,
mappedDeletedMembers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,6 @@ private static bool TryGetAnonymousTypeKey(
internal CSharpDefinitionMap PreviousDefinitions
=> (CSharpDefinitionMap)_changes.DefinitionMap;

public SynthesizedTypeMaps GetSynthesizedTypes()
{
var result = new SynthesizedTypeMaps(
Compilation.AnonymousTypeManager.GetAnonymousTypeMap(),
Compilation.AnonymousTypeManager.GetAnonymousDelegates(),
Compilation.AnonymousTypeManager.GetAnonymousDelegatesWithIndexedNames());

// Should contain all entries in previous generation.
Debug.Assert(PreviousGeneration.SynthesizedTypes.IsSubsetOf(result));

return result;
}

public override IEnumerable<Cci.INamespaceTypeDefinition> GetTopLevelTypeDefinitions(EmitContext context)
=> GetTopLevelTypeDefinitionsExcludingNoPiaAndRootModule(context, includePrivateImplementationDetails: true);

Expand All @@ -258,16 +245,6 @@ internal override MethodInstrumentation GetMethodBodyInstrumentations(MethodSymb
return _changes.DefinitionMap.GetMethodBodyInstrumentations(method);
}

internal override ImmutableArray<AnonymousTypeKey> GetPreviousAnonymousTypes()
{
return ImmutableArray.CreateRange(PreviousGeneration.SynthesizedTypes.AnonymousTypes.Keys);
}

internal override ImmutableArray<SynthesizedDelegateKey> GetPreviousAnonymousDelegates()
{
return ImmutableArray.CreateRange(PreviousGeneration.SynthesizedTypes.AnonymousDelegates.Keys);
}

internal override int GetNextAnonymousTypeIndex()
=> PreviousGeneration.GetNextAnonymousTypeIndex();

Expand Down
Loading
Loading