Skip to content

Commit

Permalink
Merge pull request #45634 from dotnet/merges/master-to-features/modul…
Browse files Browse the repository at this point in the history
…e-initializers

Merge master to features/module-initializers
  • Loading branch information
msftbot[bot] authored Jul 3, 2020
2 parents e35d0dc + 47e448e commit 8cd4e03
Show file tree
Hide file tree
Showing 61 changed files with 1,921 additions and 1,069 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#nullable enable

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
Expand Down Expand Up @@ -182,5 +183,23 @@ public void M() {{ }}
}}";
await VerifyCS.VerifyCodeFixAsync(input, input);
}

[Fact, WorkItem(45465, "https://github.com/dotnet/roslyn/issues/45465")]
public async Task LegacyModeGlobalSuppressionWithNamespaceAndDescendantsScope()
{
var target = "N:N.InvalidChild";
var input = $@"
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Scope = ""namespaceanddescendants"", Target = {{|#0:""{target}""|}})]
namespace N
{{
class C {{ }}
}}";
var expectedDiagnostic = VerifyCS.Diagnostic(AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.LegacyFormatTargetDescriptor)
.WithLocation(0)
.WithArguments(target);

await VerifyCS.VerifyCodeFixAsync(input, expectedDiagnostic, input);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ public bool HasValidTarget(
// Compilation wide suppression with a non-null target is considered invalid.
return targetSymbolString == null;
}
else if (targetScope == TargetScope.NamespaceAndDescendants)
{
// TargetSymbolResolver expects the callers to normalize 'NamespaceAndDescendants' and 'Namespace' scopes to 'Namespace' scope.
targetScope = TargetScope.Namespace;
}

var resolver = new TargetSymbolResolver(_compilation, targetScope, targetSymbolString);
resolvedSymbols = resolver.Resolve(out targetHasDocCommentIdFormat);
Expand Down
5 changes: 4 additions & 1 deletion src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6278,11 +6278,14 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>A copy constructor in a record must call a copy constructor of the base, or a parameterless object constructor if the record inherits from object.</value>
</data>
<data name="ERR_DoesNotOverrideMethodFromObject" xml:space="preserve">
<value>'{0}' does not override the method from 'object'.</value>
<value>'{0}' does not override expected method from 'object'.</value>
</data>
<data name="ERR_SealedGetHashCodeInRecord" xml:space="preserve">
<value>'{0}' cannot be sealed because containing 'record' is not sealed.</value>
</data>
<data name="ERR_DoesNotOverrideBaseEquals" xml:space="preserve">
<value>'{0}' does not override expected method from '{1}'.</value>
</data>
<data name="IDS_FeatureModuleInitializers" xml:space="preserve">
<value>module initializers</value>
</data>
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,7 @@ internal enum ErrorCode
ERR_CopyConstructorMustInvokeBaseCopyConstructor = 8868,
ERR_DoesNotOverrideMethodFromObject = 8869,
ERR_SealedGetHashCodeInRecord = 8870,
ERR_DoesNotOverrideBaseEquals = 8871,

#endregion diagnostics introduced for C# 9.0
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,14 @@ protected virtual bool IsEmptyStructType(TypeSymbol type)
return _emptyStructTypeCache.IsEmptyStructType(type);
}

#nullable enable
/// <summary>
/// Force a variable to have a slot. Returns -1 if the variable has an empty struct type.
/// </summary>
protected virtual int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bool forceSlotEvenIfEmpty = false)
{
Debug.Assert(containingSlot >= 0);
Debug.Assert(symbol != null);

if (symbol.Kind == SymbolKind.RangeVariable) return -1;

Expand Down Expand Up @@ -169,6 +171,7 @@ protected virtual int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, boo

return slot;
}
#nullable restore

private int GetSlotDepth(int slot)
{
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,10 @@ int getSlotForFieldOrProperty(Symbol member)

if (!isStatic)
{
if (MethodThisParameter is null)
{
return -1;
}
thisSlot = GetOrCreateSlot(MethodThisParameter);
if (thisSlot < 0)
{
Expand Down Expand Up @@ -1304,6 +1308,7 @@ static MethodSymbol getTopLevelMethod(MethodSymbol method)
}
}

#nullable enable
protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bool forceSlotEvenIfEmpty = false)
{

Expand All @@ -1312,6 +1317,7 @@ protected override int GetOrCreateSlot(Symbol symbol, int containingSlot = 0, bo

return base.GetOrCreateSlot(symbol, containingSlot, forceSlotEvenIfEmpty);
}
#nullable restore

private void VisitAndUnsplitAll<T>(ImmutableArray<T> nodes) where T : BoundNode
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3002,7 +3002,7 @@ private void AddSynthesizedRecordMembersIfNecessary(MembersAndInitializersBuilde
getOtherEquals(otherEqualsMethods, equalityContract);

var thisEquals = addThisEquals(equalityContract, otherEqualsMethod: otherEqualsMethods.Count == 0 ? null : otherEqualsMethods[0]);
addOtherEquals(otherEqualsMethods, equalityContract, thisEquals);
addOtherEquals();
addObjectEquals(thisEquals);
addHashCode(equalityContract);

Expand Down Expand Up @@ -3148,15 +3148,15 @@ void addHashCode(PropertySymbol equalityContract)
ImmutableArray<CustomModifier>.Empty,
ImmutableArray<MethodSymbol>.Empty);

if (!memberSignatures.TryGetValue(targetMethod, out Symbol? contender))
if (!memberSignatures.TryGetValue(targetMethod, out Symbol? existingHashCodeMethod))
{
var hashCode = new SynthesizedRecordGetHashCode(this, equalityContract, memberOffset: members.Count, diagnostics);
members.Add(hashCode);
}
else
{
var method = (MethodSymbol)contender;
if (!SynthesizedRecordObjectMethod.VerifyOerridesMethodFromObject(method, diagnostics) && method.IsSealed && !IsSealed)
var method = (MethodSymbol)existingHashCodeMethod;
if (!SynthesizedRecordObjectMethod.VerifyOverridesMethodFromObject(method, SpecialType.System_Int32, diagnostics) && method.IsSealed && !IsSealed)
{
diagnostics.Add(ErrorCode.ERR_SealedGetHashCodeInRecord, method.Locations[0], method);
}
Expand Down Expand Up @@ -3210,21 +3210,12 @@ static void getOtherEquals(ArrayBuilder<MethodSymbol> otherEqualsMethods, Proper
}
}

void addOtherEquals(ArrayBuilder<MethodSymbol> otherEqualsMethods, PropertySymbol equalityContract, MethodSymbol thisEquals)
void addOtherEquals()
{
foreach (var otherEqualsMethod in otherEqualsMethods)
if (!BaseTypeNoUseSiteDiagnostics.IsObjectType())
{
var method = new SynthesizedRecordEquals(
this,
parameterType: otherEqualsMethod.Parameters[0].Type,
isOverride: true,
equalityContract,
otherEqualsMethod: thisEquals,
memberOffset: members.Count);
if (!memberSignatures.ContainsKey(method))
{
members.Add(method);
}
var method = new SynthesizedRecordBaseEquals(this, memberOffset: members.Count, diagnostics);
members.Add(method);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected override ImmutableArray<TypeParameterSymbol> MakeTypeParameters(CSharp
}
}

protected override (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters, bool IsVararg, ImmutableArray<TypeParameterConstraintClause> DeclaredConstraintsForOverrideOrImplement) MakeParametersAndBindReturnType(DiagnosticBag diagnostics)
protected override (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters, bool IsVararg, ImmutableArray<TypeParameterConstraintClause> DeclaredConstraintsForOverrideOrImplementation) MakeParametersAndBindReturnType(DiagnosticBag diagnostics)
{
var syntax = GetSyntax();
var withTypeParamsBinder = this.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree).GetBinder(syntax.ReturnType, syntax, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ protected override void MethodChecks(DiagnosticBag diagnostics)
return;
}

protected abstract (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters, bool IsVararg, ImmutableArray<TypeParameterConstraintClause> DeclaredConstraintsForOverrideOrImplement) MakeParametersAndBindReturnType(DiagnosticBag diagnostics);
protected abstract (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters, bool IsVararg, ImmutableArray<TypeParameterConstraintClause> DeclaredConstraintsForOverrideOrImplementation) MakeParametersAndBindReturnType(DiagnosticBag diagnostics);

protected abstract void ExtensionMethodChecks(DiagnosticBag diagnostics);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
/// <summary>
/// If the record type is derived from a base record type Base, the record type includes
/// a synthesized override of the strongly-typed Equals(Base other). The synthesized
/// override is sealed. It is an error if the override is declared explicitly.
/// The synthesized override returns Equals((object?)other).
/// </summary>
internal sealed class SynthesizedRecordBaseEquals : SynthesizedRecordOrdinaryMethod
{
public SynthesizedRecordBaseEquals(SourceMemberContainerTypeSymbol containingType, int memberOffset, DiagnosticBag diagnostics)
: base(containingType, WellKnownMemberNames.ObjectEquals, memberOffset, diagnostics)
{
}

protected override DeclarationModifiers MakeDeclarationModifiers(DeclarationModifiers allowedModifiers, DiagnosticBag diagnostics)
{
const DeclarationModifiers result = DeclarationModifiers.Public | DeclarationModifiers.Override | DeclarationModifiers.Sealed;
Debug.Assert((result & ~allowedModifiers) == 0);
return result;
}

protected override (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters, bool IsVararg, ImmutableArray<TypeParameterConstraintClause> DeclaredConstraintsForOverrideOrImplementation) MakeParametersAndBindReturnType(DiagnosticBag diagnostics)
{
var compilation = DeclaringCompilation;
var location = ReturnTypeLocation;
return (ReturnType: TypeWithAnnotations.Create(Binder.GetSpecialType(compilation, SpecialType.System_Boolean, location, diagnostics)),
Parameters: ImmutableArray.Create<ParameterSymbol>(
new SourceSimpleParameterSymbol(owner: this,
TypeWithAnnotations.Create(ContainingType.BaseTypeNoUseSiteDiagnostics, NullableAnnotation.Annotated),
ordinal: 0, RefKind.None, "", isDiscard: false, Locations)),
IsVararg: false,
DeclaredConstraintsForOverrideOrImplementation: ImmutableArray<TypeParameterConstraintClause>.Empty);
}

protected override int GetParameterCountFromSyntax() => 1;

protected override void MethodChecks(DiagnosticBag diagnostics)
{
base.MethodChecks(diagnostics);

var overridden = OverriddenMethod;

if (overridden is null)
{
return;
}

if (overridden is object &&
!overridden.ContainingType.Equals(ContainingType.BaseTypeNoUseSiteDiagnostics, TypeCompareKind.AllIgnoreOptions))
{
diagnostics.Add(ErrorCode.ERR_DoesNotOverrideBaseEquals, Locations[0], this, ContainingType.BaseTypeNoUseSiteDiagnostics);
}
}

internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
{
var F = new SyntheticBoundNodeFactory(this, this.SyntaxNode, compilationState, diagnostics);

try
{
var retExpr = F.Call(
F.This(),
ContainingType.GetMembersUnordered().OfType<SynthesizedRecordObjEquals>().Single(),
F.Convert(F.SpecialType(SpecialType.System_Object), F.Parameter(Parameters[0])));

F.CloseMethod(F.Block(F.Return(retExpr)));
}
catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
{
diagnostics.Add(ex.Diagnostic);
F.CloseMethod(F.ThrowNull());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,17 @@ internal override IEnumerable<SecurityAttribute> GetSecurityInformation()
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
{
var F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics);
F.CurrentFunction = this;
F.CloseMethod(F.Block(F.Return(F.Typeof(ContainingType))));

try
{
F.CurrentFunction = this;
F.CloseMethod(F.Block(F.Return(F.Typeof(ContainingType))));
}
catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
{
diagnostics.Add(ex.Diagnostic);
F.CloseMethod(F.ThrowNull());
}
}
}
}
Expand Down
Loading

0 comments on commit 8cd4e03

Please sign in to comment.