未验证 提交 51f1d2cc 编写于 作者: J Julien Couvreur 提交者: GitHub

Honor Disallow/AllowNull and Maybe/NotNull on properties (#36444)

上级 b7ec2ef8
......@@ -142,7 +142,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(ContainingAssembly.GetSpecialType(SpecialType.System_Void)); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -139,7 +139,7 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return this.TypeMap.SubstituteType(this.BaseMethod.OriginalDefinition.ReturnTypeWithAnnotations); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => BaseMethod.ReturnTypeAnnotationAttributes;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => BaseMethod.ReturnTypeFlowAnalysisAnnotations;
public sealed override bool IsVararg
{
......
......@@ -97,7 +97,7 @@ public sealed override bool IsVararg
get { return false; }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public sealed override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -650,7 +650,11 @@ internal bool ShouldEmitAttribute(Symbol target, bool isReturnType, bool emittin
case SymbolKind.Property:
if (IsTargetAttribute(target, AttributeDescription.IndexerNameAttribute) ||
IsTargetAttribute(target, AttributeDescription.SpecialNameAttribute))
IsTargetAttribute(target, AttributeDescription.SpecialNameAttribute) ||
IsTargetAttribute(target, AttributeDescription.DisallowNullAttribute) ||
IsTargetAttribute(target, AttributeDescription.AllowNullAttribute) ||
IsTargetAttribute(target, AttributeDescription.MaybeNullAttribute) ||
IsTargetAttribute(target, AttributeDescription.NotNullAttribute))
{
return false;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
/// <summary>
/// Information decoded from well-known custom attributes applied on a property.
/// </summary>
internal sealed class PropertyWellKnownAttributeData : CommonPropertyWellKnownAttributeData
{
private bool _hasDisallowNullAttribute;
public bool HasDisallowNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasDisallowNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasDisallowNullAttribute = value;
SetDataStored();
}
}
private bool _hasAllowNullAttribute;
public bool HasAllowNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasAllowNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasAllowNullAttribute = value;
SetDataStored();
}
}
private bool _hasMaybeNullAttribute;
public bool HasMaybeNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasMaybeNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasMaybeNullAttribute = value;
SetDataStored();
}
}
private bool _hasNotNullAttribute;
public bool HasNotNullAttribute
{
get
{
VerifySealed(expected: true);
return _hasNotNullAttribute;
}
set
{
VerifySealed(expected: false);
_hasNotNullAttribute = value;
SetDataStored();
}
}
}
}
......@@ -161,7 +161,7 @@ public override bool ReturnsVoid
get { return this.ReturnType.IsVoidType(); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override bool IsVararg
{
......
......@@ -526,7 +526,7 @@ internal override int ParameterCount
public override TypeWithAnnotations ReturnTypeWithAnnotations => Signature.ReturnParam.TypeWithAnnotations;
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => Signature.ReturnParam.FlowAnalysisAnnotations;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => Signature.ReturnParam.FlowAnalysisAnnotations;
public override ImmutableArray<CustomModifier> RefCustomModifiers => Signature.ReturnParam.RefCustomModifiers;
......
......@@ -209,7 +209,7 @@ public bool ReturnsByRefReadonly
/// </summary>
public TypeSymbol ReturnType => ReturnTypeWithAnnotations.Type;
public abstract FlowAnalysisAnnotations ReturnTypeAnnotationAttributes { get; }
public abstract FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations { get; }
/// <summary>
/// Returns the type arguments that have been substituted for the type parameters.
......
......@@ -344,7 +344,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _typeMap.SubstituteType(_reducedFrom.ReturnTypeWithAnnotations); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => _reducedFrom.ReturnTypeAnnotationAttributes;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => _reducedFrom.ReturnTypeFlowAnalysisAnnotations;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
......
......@@ -65,7 +65,7 @@ internal sealed class SignatureOnlyMethodSymbol : MethodSymbol
public override TypeWithAnnotations ReturnTypeWithAnnotations { get { return _returnType; } }
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers { get { return _refCustomModifiers; } }
......
......@@ -179,7 +179,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _returnType; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
// In error recovery and type inference scenarios we do not know the return type
// until after the body is bound, but the symbol is created before the body
......
......@@ -205,7 +205,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override RefKind RefKind => _refKind;
......
......@@ -358,7 +358,7 @@ public override bool ReturnsVoid
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes =>
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations =>
DecodeReturnTypeAnnotationAttributes(GetDecodedReturnTypeWellKnownAttributeData());
public sealed override MethodKind MethodKind
......
......@@ -368,6 +368,28 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations
{
get
{
if (MethodKind == MethodKind.PropertySet)
{
return FlowAnalysisAnnotations.None;
}
var result = FlowAnalysisAnnotations.None;
if (_property.HasMaybeNull)
{
result |= FlowAnalysisAnnotations.MaybeNull;
}
if (_property.HasNotNull)
{
result |= FlowAnalysisAnnotations.NotNull;
}
return result;
}
}
private TypeWithAnnotations ComputeReturnType(DiagnosticBag diagnostics)
{
if (this.MethodKind == MethodKind.PropertyGet)
......@@ -653,6 +675,22 @@ private ImmutableArray<ParameterSymbol> ComputeParameters(DiagnosticBag diagnost
return parameters.ToImmutableAndFree();
}
internal override void AddSynthesizedReturnTypeAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<SynthesizedAttributeData> attributes)
{
base.AddSynthesizedReturnTypeAttributes(moduleBuilder, ref attributes);
var compilation = this.DeclaringCompilation;
var annotations = ReturnTypeFlowAnalysisAnnotations;
if ((annotations & FlowAnalysisAnnotations.MaybeNull) != 0)
{
AddSynthesizedAttribute(ref attributes, new SynthesizedAttributeData(_property.MaybeNullAttributeIfExists));
}
if ((annotations & FlowAnalysisAnnotations.NotNull) != 0)
{
AddSynthesizedAttribute(ref attributes, new SynthesizedAttributeData(_property.NotNullAttributeIfExists));
}
}
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<SynthesizedAttributeData> attributes)
{
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
......
......@@ -1209,7 +1209,7 @@ public sealed override ImmutableArray<CSharpAttributeData> GetAttributes()
/// <remarks>
/// Forces binding and decoding of attributes.
/// </remarks>
private CommonPropertyWellKnownAttributeData GetDecodedWellKnownAttributeData()
private PropertyWellKnownAttributeData GetDecodedWellKnownAttributeData()
{
var attributesBag = _lazyCustomAttributesBag;
if (attributesBag == null || !attributesBag.IsDecodedWellKnownAttributeDataComputed)
......@@ -1217,7 +1217,7 @@ private CommonPropertyWellKnownAttributeData GetDecodedWellKnownAttributeData()
attributesBag = this.GetAttributesBag();
}
return (CommonPropertyWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
return (PropertyWellKnownAttributeData)attributesBag.DecodedWellKnownAttributeData;
}
/// <summary>
......@@ -1356,11 +1356,11 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
{
arguments.GetOrCreateData<CommonPropertyWellKnownAttributeData>().HasSpecialNameAttribute = true;
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasSpecialNameAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
{
arguments.GetOrCreateData<CommonPropertyWellKnownAttributeData>().HasExcludeFromCodeCoverageAttribute = true;
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasExcludeFromCodeCoverageAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute))
{
......@@ -1391,8 +1391,75 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu
// NullableAttribute should not be set explicitly.
arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.DisallowNullAttribute))
{
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasDisallowNullAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.AllowNullAttribute))
{
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasAllowNullAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.MaybeNullAttribute))
{
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasMaybeNullAttribute = true;
}
else if (attribute.IsTargetAttribute(this, AttributeDescription.NotNullAttribute))
{
arguments.GetOrCreateData<PropertyWellKnownAttributeData>().HasNotNullAttribute = true;
}
}
internal bool HasDisallowNull
{
get
{
var data = GetDecodedWellKnownAttributeData();
return data != null && data.HasDisallowNullAttribute;
}
}
internal bool HasAllowNull
{
get
{
var data = GetDecodedWellKnownAttributeData();
return data != null && data.HasAllowNullAttribute;
}
}
internal bool HasMaybeNull
{
get
{
var data = GetDecodedWellKnownAttributeData();
return data != null && data.HasMaybeNullAttribute;
}
}
internal bool HasNotNull
{
get
{
var data = GetDecodedWellKnownAttributeData();
return data != null && data.HasNotNullAttribute;
}
}
internal SourceAttributeData DisallowNullAttributeIfExists
=> FindAttribute(AttributeDescription.DisallowNullAttribute);
internal SourceAttributeData AllowNullAttributeIfExists
=> FindAttribute(AttributeDescription.AllowNullAttribute);
internal SourceAttributeData MaybeNullAttributeIfExists
=> FindAttribute(AttributeDescription.MaybeNullAttribute);
internal SourceAttributeData NotNullAttributeIfExists
=> FindAttribute(AttributeDescription.NotNullAttribute);
private SourceAttributeData FindAttribute(AttributeDescription attributeDescription)
=> (SourceAttributeData)GetAttributes().First(a => a.IsTargetAttribute(this, attributeDescription));
internal override void PostDecodeWellKnownAttributes(ImmutableArray<CSharpAttributeData> boundAttributes, ImmutableArray<AttributeSyntax> allAttributeSyntaxNodes, DiagnosticBag diagnostics, AttributeLocation symbolPart, WellKnownAttributeData decodedData)
{
Debug.Assert(!boundAttributes.IsDefault);
......
......@@ -30,5 +30,18 @@ internal SynthesizedAttributeData(MethodSymbol wellKnownMember, ImmutableArray<T
Debug.Assert(!arguments.IsDefault);
Debug.Assert(!namedArguments.IsDefault); // Frequently empty though.
}
internal SynthesizedAttributeData(SourceAttributeData original)
: base(
applicationNode: original.ApplicationSyntaxReference,
attributeClass: original.AttributeClass,
attributeConstructor: original.AttributeConstructor,
constructorArguments: original.CommonConstructorArguments,
constructorArgumentsSourceIndices: original.ConstructorArgumentsSourceIndices,
namedArguments: original.CommonNamedArguments,
hasErrors: original.HasErrors,
isConditionallyOmitted: original.IsConditionallyOmitted)
{
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
......@@ -24,6 +25,26 @@ public SynthesizedAccessorValueParameterSymbol(SourceMemberMethodSymbol accessor
{
}
internal override FlowAnalysisAnnotations FlowAnalysisAnnotations
{
get
{
var result = FlowAnalysisAnnotations.None;
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
{
if (property.HasDisallowNull)
{
result |= FlowAnalysisAnnotations.DisallowNull;
}
if (property.HasAllowNull)
{
result |= FlowAnalysisAnnotations.AllowNull;
}
}
return result;
}
}
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get
......@@ -37,7 +58,6 @@ public override bool IsImplicitlyDeclared
get { return true; }
}
protected override IAttributeTargetSymbol AttributeOwner
{
get { return (SourceMemberMethodSymbol)this.ContainingSymbol; }
......@@ -49,5 +69,23 @@ internal override OneOrMany<SyntaxList<AttributeListSyntax>> GetAttributeDeclara
var accessor = (SourceMemberMethodSymbol)this.ContainingSymbol;
return accessor.GetAttributeDeclarations();
}
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<SynthesizedAttributeData> attributes)
{
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
if (ContainingSymbol is SourcePropertyAccessorSymbol propertyAccessor && propertyAccessor.AssociatedSymbol is SourcePropertySymbol property)
{
var annotations = FlowAnalysisAnnotations;
if ((annotations & FlowAnalysisAnnotations.DisallowNull) != 0)
{
AddSynthesizedAttribute(ref attributes, new SynthesizedAttributeData(property.DisallowNullAttributeIfExists));
}
if ((annotations & FlowAnalysisAnnotations.AllowNull) != 0)
{
AddSynthesizedAttribute(ref attributes, new SynthesizedAttributeData(property.AllowNullAttributeIfExists));
}
}
}
}
}
......@@ -227,7 +227,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(_returnType); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -138,7 +138,7 @@ public override bool ReturnsVoid
get { return ReturnType.IsVoidType(); }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override MethodKind MethodKind
{
......
......@@ -116,7 +116,7 @@ public override DllImportData GetDllImportData()
return null;
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation
{
......
......@@ -99,7 +99,7 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _interfaceMethod.ReturnTypeWithAnnotations; }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<ParameterSymbol> Parameters
{
......
......@@ -151,7 +151,7 @@ public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(ContainingAssembly.GetSpecialType(SpecialType.System_Void)); }
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
......
......@@ -140,7 +140,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return TypeWithAnnotations.Create(_returnType); }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
......
......@@ -229,7 +229,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -188,7 +188,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -136,7 +136,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
......
......@@ -297,7 +297,7 @@ internal override bool HasRuntimeSpecialName
}
}
public sealed override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => UnderlyingMethod.ReturnTypeAnnotationAttributes;
public sealed override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => UnderlyingMethod.ReturnTypeFlowAnalysisAnnotations;
internal override bool ReturnValueIsMarshalledExplicitly
{
......
......@@ -295,7 +295,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
}
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
......
......@@ -155,7 +155,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { return _returnType; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
bool Cci.ISignature.ReturnValueIsByRef
{
......
......@@ -128,7 +128,7 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations
get { throw ExceptionUtilities.Unreachable; }
}
public override FlowAnalysisAnnotations ReturnTypeAnnotationAttributes => FlowAnalysisAnnotations.None;
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableArray<CustomModifier> RefCustomModifiers
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册