Skip to content

Commit

Permalink
EnC: Implement support for editing types with primary constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Jun 22, 2023
1 parent 1418690 commit 9283d26
Show file tree
Hide file tree
Showing 32 changed files with 4,953 additions and 2,891 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ internal EditAndContinueTest AddGeneration(SourceWithMarkedNodes source, Semanti
throw new Exception($"Exception during generation #{_generations.Count}. See inner stack trace for details.", ex);
}

Assert.Empty(diff.EmitResult.Diagnostics);

// EncVariableSlotAllocator attempted to map from current source to the previous one,
// but the mapping failed for these nodes. Mark the nodes in sources with node markers <N:x>...</N:x>.
Assert.Empty(unmappedNodes);
Expand Down Expand Up @@ -155,13 +157,18 @@ private ImmutableArray<SemanticEdit> GetSemanticEdits(

return ImmutableArray.CreateRange(edits.Select(e =>
{
var oldSymbol = e.SymbolProvider(oldCompilation);
var oldSymbol = e.Kind is SemanticEditKind.Update or SemanticEditKind.Delete ? e.SymbolProvider(oldCompilation) : null;

// for delete the new symbol is the new containing type
var newSymbol = e.NewSymbolProvider(newCompilation);

Func<SyntaxNode, SyntaxNode?>? syntaxMap;
if (e.PreserveLocalVariables)
{
Assert.Equal(SemanticEditKind.Update, e.Kind);
Debug.Assert(oldSymbol != null);
Debug.Assert(newSymbol != null);

syntaxMap = syntaxMapFromMarkers ?? EditAndContinueTestBase.GetEquivalentNodesMap(
((Public.MethodSymbol)newSymbol).GetSymbol<MethodSymbol>(), ((Public.MethodSymbol)oldSymbol).GetSymbol<MethodSymbol>());
}
Expand Down

Large diffs are not rendered by default.

41 changes: 34 additions & 7 deletions src/Compilers/Test/Utilities/CSharp/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,25 +163,52 @@ private static ImmutableArray<string> SplitMemberName(string name)
}

public static Symbol GetMember(this CSharpCompilation compilation, string qualifiedName)
=> compilation.GlobalNamespace.GetMember(qualifiedName);

public static ISymbol GetMember(this Compilation compilation, string qualifiedName)
=> compilation.GlobalNamespace.GetMember(qualifiedName);

public static T GetMember<T>(this CSharpCompilation compilation, string qualifiedName) where T : Symbol
=> (T)compilation.GlobalNamespace.GetMember(qualifiedName);

public static T GetMember<T>(this Compilation compilation, string qualifiedName) where T : ISymbol
=> (T)compilation.GlobalNamespace.GetMember(qualifiedName);

public static IMethodSymbol GetCopyConstructor(this Compilation compilation, string qualifiedTypeName)
{
return compilation.GlobalNamespace.GetMember(qualifiedName);
var type = compilation.GetMember<INamedTypeSymbol>(qualifiedTypeName);
return type.InstanceConstructors.Single(c => c.Parameters is [{ Type: var parameterType }] && parameterType.Equals(type, SymbolEqualityComparer.Default));
}

public static ISymbol GetMember(this Compilation compilation, string qualifiedName)
public static IMethodSymbol GetPrimaryConstructor(this Compilation compilation, string qualifiedTypeName)
{
return compilation.GlobalNamespace.GetMember(qualifiedName);
var type = compilation.GetMember<INamedTypeSymbol>(qualifiedTypeName);
return type.InstanceConstructors.Single(c => c.DeclaringSyntaxReferences.Any(r => r.GetSyntax() is TypeDeclarationSyntax));
}

public static T GetMember<T>(this CSharpCompilation compilation, string qualifiedName) where T : Symbol
public static IMethodSymbol GetParameterlessConstructor(this Compilation compilation, string qualifiedTypeName)
{
return (T)compilation.GlobalNamespace.GetMember(qualifiedName);
var type = compilation.GetMember<INamedTypeSymbol>(qualifiedTypeName);
return type.InstanceConstructors.Single(c => c.Parameters is []);
}

public static T GetMember<T>(this Compilation compilation, string qualifiedName) where T : ISymbol
public static IMethodSymbol GetIEquatableEquals(this Compilation compilation, string qualifiedTypeName)
{
return (T)compilation.GlobalNamespace.GetMember(qualifiedName);
var type = compilation.GetMember<INamedTypeSymbol>(qualifiedTypeName);
return type.GetMembers("Equals").OfType<IMethodSymbol>().Single(m => m.Parameters is [{ Type: var parameterType }] && parameterType.Equals(type, SymbolEqualityComparer.Default));
}

public static IMethodSymbol GetPrimaryDeconstructor(this Compilation compilation, string qualifiedTypeName)
{
var primaryConstructor = compilation.GetPrimaryConstructor(qualifiedTypeName);
return primaryConstructor.ContainingType.GetMembers("Deconstruct").OfType<IMethodSymbol>().Single(
m => m.Parameters.Length == primaryConstructor.Parameters.Length &&
m.Parameters.All(p => p.RefKind == RefKind.Out && p.Type.Equals(primaryConstructor.Parameters[p.Ordinal].Type, SymbolEqualityComparer.Default)));
}

public static ImmutableArray<T> GetMembers<T>(this Compilation compilation, string qualifiedName) where T : ISymbol
=> GetMembers(compilation, qualifiedName).SelectAsArray(s => (T)s.ISymbol);

public static ImmutableArray<Symbol> GetMembers(this Compilation compilation, string qualifiedName)
{
NamespaceOrTypeSymbol lastContainer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ internal enum MethodKind
public static string GetResource(string keyword, string symbolDisplayName)
=> string.Format(FeaturesResources.member_kind_and_name, TryGetResource(keyword) ?? throw ExceptionUtilities.UnexpectedValue(keyword), symbolDisplayName);

public static string GetResource(string keyword, string symbolDisplayName, string containerKeyword, string containerDisplayName)
=> string.Format(
FeaturesResources.symbol_kind_and_name_of_member_kind_and_name,
TryGetResource(keyword) ?? throw ExceptionUtilities.UnexpectedValue(keyword),
symbolDisplayName,
TryGetResource(containerKeyword) ?? throw ExceptionUtilities.UnexpectedValue(containerKeyword),
containerDisplayName);

public static string GetResource(string keyword)
=> TryGetResource(keyword) ?? throw ExceptionUtilities.UnexpectedValue(keyword);

Expand All @@ -63,6 +71,8 @@ public static string GetResource(string keyword)
"field" => FeaturesResources.field,
"method" => FeaturesResources.method,
"property" => FeaturesResources.property_,
"property getter" => CSharpFeaturesResources.property_getter,
"property setter" => CSharpFeaturesResources.property_setter,
"auto-property" => FeaturesResources.auto_property,
"indexer" => CSharpFeaturesResources.indexer,
"indexer getter" => CSharpFeaturesResources.indexer_getter,
Expand Down
Loading

0 comments on commit 9283d26

Please sign in to comment.