Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IMethodSymbol.IsReadOnly to public API #34514

Merged
Show file tree
Hide file tree
Changes from 7 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
10 changes: 8 additions & 2 deletions src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,13 @@ internal virtual bool IsExplicitInterfaceImplementation
get { return ExplicitInterfaceImplementations.Any(); }
}

// PROTOTYPE: this should become public API
/// <summary>
/// Indicates whether the method is declared readonly, i.e.
/// whether 'this' is readonly in the scope of the method.
/// See also <see cref="IsEffectivelyReadOnly"/>
/// </summary>
internal abstract bool IsDeclaredReadOnly { get; }

// PROTOTYPE: this should become public API
/// <summary>
/// Indicates whether the method is effectively readonly,
/// by either the method or the containing type being marked readonly.
Expand Down Expand Up @@ -1063,6 +1061,14 @@ IMethodSymbol IMethodSymbol.ConstructedFrom
}
}

bool IMethodSymbol.IsReadOnly
{
get
{
return this.IsEffectivelyReadOnly;
}
}

IMethodSymbol IMethodSymbol.OriginalDefinition
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,78 @@ public readonly int M()
Assert.True(method.IsEffectivelyReadOnly);
}

[Fact]
public void ReadOnlyMembers_SemanticModel()
{
var csharp = @"
using System;

public struct S1
{
public void M1() {}
public readonly void M2() {}

public int P1 { get; set; }
public readonly int P2 => 42;
public int P3 { readonly get => 123; }
public int P4 { readonly set {} }
public static int P5 { get; set; }
public readonly event Action<EventArgs> E { add {} remove {} }
}

public readonly struct S2
{
public void M1() {}
public int P1 { get; }
public int P2 => 42;
public int P3 { set {} }
public static int P4 { get; set; }
public event Action<EventArgs> E { add {} remove {} }
}
";
Compilation comp = CreateCompilation(csharp);
var s1 = (INamedTypeSymbol)comp.GetSymbolsWithName("S1").Single();

Assert.False(getMethod(s1, "M1").IsReadOnly);

Assert.True(getMethod(s1, "M2").IsReadOnly);

Assert.True(getProperty(s1, "P1").GetMethod.IsReadOnly);
Assert.False(getProperty(s1, "P1").SetMethod.IsReadOnly);

Assert.True(getProperty(s1, "P2").GetMethod.IsReadOnly);

Assert.True(getProperty(s1, "P3").GetMethod.IsReadOnly);

Assert.True(getProperty(s1, "P4").SetMethod.IsReadOnly);

Assert.False(getProperty(s1, "P5").GetMethod.IsReadOnly);
Assert.False(getProperty(s1, "P5").SetMethod.IsReadOnly);

Assert.True(getEvent(s1, "E").AddMethod.IsReadOnly);

Assert.True(getEvent(s1, "E").RemoveMethod.IsReadOnly);

var s2 = comp.GetMember<NamedTypeSymbol>("S2");
Assert.True(getMethod(s2, "M1").IsReadOnly);

Assert.True(getProperty(s2, "P1").GetMethod.IsReadOnly);

Assert.True(getProperty(s2, "P2").GetMethod.IsReadOnly);

Assert.True(getProperty(s2, "P3").SetMethod.IsReadOnly);

Assert.False(getProperty(s2, "P4").GetMethod.IsReadOnly);
Assert.False(getProperty(s2, "P4").SetMethod.IsReadOnly);

Assert.True(getEvent(s2, "E").AddMethod.IsReadOnly);
Assert.True(getEvent(s2, "E").RemoveMethod.IsReadOnly);

static IMethodSymbol getMethod(INamedTypeSymbol symbol, string name) => (IMethodSymbol)symbol.GetMembers(name).Single();
static IPropertySymbol getProperty(INamedTypeSymbol symbol, string name) => (IPropertySymbol)symbol.GetMembers(name).Single();
static IEventSymbol getEvent(INamedTypeSymbol symbol, string name) => (IEventSymbol)symbol.GetMembers(name).Single();
}

[Fact]
public void ReadOnlyClass()
{
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*REMOVED*Microsoft.CodeAnalysis.Operations.IEventAssignmentOperation.EventReference.get -> Microsoft.CodeAnalysis.Operations.IEventReferenceOperation
Microsoft.CodeAnalysis.IMethodSymbol.IsReadOnly.get -> bool
Microsoft.CodeAnalysis.Operations.IVariableDeclarationOperation.IgnoredDimensions.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IOperation>
abstract Microsoft.CodeAnalysis.Compilation.ClassifyCommonConversion(Microsoft.CodeAnalysis.ITypeSymbol source, Microsoft.CodeAnalysis.ITypeSymbol destination) -> Microsoft.CodeAnalysis.Operations.CommonConversion
abstract Microsoft.CodeAnalysis.Compilation.ContainsSymbolsWithName(string name, Microsoft.CodeAnalysis.SymbolFilter filter = Microsoft.CodeAnalysis.SymbolFilter.TypeAndMember, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> bool
Expand Down
6 changes: 6 additions & 0 deletions src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ public interface IMethodSymbol : ISymbol
/// </summary>
IMethodSymbol ConstructedFrom { get; }

/// <summary>
/// Indicates whether the method is readonly, i.e.
/// whether 'this' is 'ref readonly' in the scope of the method.
/// </summary>
bool IsReadOnly { get; }

/// <summary>
/// Get the original definition of this symbol. If this symbol is derived from another
/// symbol by (say) type substitution, this gets the original symbol, as it was defined in
Expand Down
9 changes: 9 additions & 0 deletions src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property

''' <summary>
''' Always returns false because the 'readonly members' feature is not available in VB.
''' </summary>
Private ReadOnly Property IMethodSymbol_IsReadOnly As Boolean Implements IMethodSymbol.IsReadOnly
Get
Return False
End Get
End Property

''' <summary>
''' Returns true if this method has no return type; i.e., is a Sub instead of a Function.
''' </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public WrappedMethodSymbol(IMethodSymbol methodSymbol, bool canImplementImplicit

public IMethodSymbol ConstructedFrom => _symbol.ConstructedFrom;

public bool IsReadOnly => _symbol.IsReadOnly;

public ImmutableArray<IMethodSymbol> ExplicitInterfaceImplementations
{
get
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// 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.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Editing;

Expand Down Expand Up @@ -39,6 +38,7 @@ protected CodeGenerationAbstractMethodSymbol(
public abstract ImmutableArray<ITypeParameterSymbol> TypeParameters { get; }
public abstract ImmutableArray<IParameterSymbol> Parameters { get; }
public abstract IMethodSymbol ConstructedFrom { get; }
public abstract bool IsReadOnly { get; }
public abstract IMethodSymbol OverriddenMethod { get; }
public abstract IMethodSymbol ReducedFrom { get; }
public abstract ITypeSymbol GetTypeInferredDuringReduction(ITypeParameterSymbol reducedFromTypeParameter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public override ImmutableArray<IParameterSymbol> Parameters

public override IMethodSymbol ConstructedFrom => _constructedFrom;

public override bool IsReadOnly => _constructedFrom.IsReadOnly;

public override IMethodSymbol OverriddenMethod =>
// TODO(cyrusn): Construct this.
_constructedFrom.OverriddenMethod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Editing;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CodeGeneration
{
Expand Down Expand Up @@ -85,6 +86,8 @@ public override ImmutableArray<ITypeSymbol> TypeArguments

public override IMethodSymbol ConstructedFrom => this;

public override bool IsReadOnly => throw ExceptionUtilities.Unreachable;

public override IMethodSymbol OverriddenMethod => null;

public override IMethodSymbol ReducedFrom => null;
Expand Down