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

Value not contained mutability accessibility more #549

Open
wants to merge 10 commits into
base: net233
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ type FcsErrorsStageProcessBase(fsFile, daemonProcess) =
| ValueNotContainedMutability ->
if error.Message.EndsWith("The mutability attributes differ") then
createHighlightingFromNodeWithMessage ValueNotContainedMutabilityAttributesDifferError range error
elif error.Message.EndsWith("The accessibility specified in the signature is more than that specified in the implementation") then
let refHighlighting = createHighlightingFromNodeWithMessage ValueNotContainedMutabilityAccessibilityMoreInBindingError range error
let memberHighlighting = createHighlightingFromParentNodeWithMessage ValueNotContainedMutabilityAccessibilityMoreInMemberError range error
if isNotNull refHighlighting then refHighlighting
elif isNotNull memberHighlighting then memberHighlighting
else createGenericHighlighting error range
else
createGenericHighlighting error range

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
<Compile Include="src\QuickFixes\RemovePatternArgumentFix.fs" />
<Compile Include="src\QuickFixes\AddSetterFix.fs" />
<Compile Include="src\QuickFixes\UpdateMutabilityInSignatureFix.fs" />
<Compile Include="src\QuickFixes\UpdateAccessibilityInSignatureBindingFix.fs" />
<Compile Include="src\QuickFixes\UpdateAccessibilityInSignatureMemberFix.fs" />
<ErrorsGen Include="..\FSharp.Psi.Services\src\Daemon\Highlightings\Errors.xml">
<Mode>QUICKFIX</Mode>
<Namespace>JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes</Namespace>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes

open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Resources.Shell
open JetBrains.ReSharper.Plugins.FSharp.Psi

type UpdateAccessibilityInSignatureBindingFix(error: ValueNotContainedMutabilityAccessibilityMoreInBindingError) =
inherit FSharpQuickFixBase()

let tryFindBindingSignatureAccessRights (declaredElement: IFSharpMember) =
declaredElement.GetDeclarations()
|> Seq.tryPick (function
| :? IReferencePat as pat when pat.IsFSharpSigFile() ->
match pat.DeclaredElement.As<IFSharpMember>() with
| null -> None
| sigMember ->
let bindingSignature = BindingSignatureNavigator.GetByHeadPattern(pat)
if isNull bindingSignature then None else
Some (bindingSignature, sigMember.GetAccessRights())
| _ -> None
)

let tryFindImplementationBindingInfo (pat: ITopReferencePat) =
if isNull pat then None else

match pat.DeclaredElement.As<IFSharpMember>() with
| null -> None
| fsMember -> Some fsMember

let mutable implAccessRights = AccessRights.NONE
let mutable bindingSignature = null

override x.Text = $"Update accessibility for {error.ReferenceName.Identifier.Name} in signature"

override x.IsAvailable _ =
let topPat = TopReferencePatNavigator.GetByReferenceName(error.ReferenceName)
match tryFindImplementationBindingInfo topPat with
| None -> false
| Some implDeclaredElement ->
match tryFindBindingSignatureAccessRights implDeclaredElement with
| None -> false
| Some (bindingSig, sigAccessRights) ->
implAccessRights <- implDeclaredElement.GetAccessRights()
bindingSignature <- bindingSig
implAccessRights <> sigAccessRights

override x.ExecutePsiTransaction _ =
use writeCookie = WriteLockCookie.Create(error.ReferenceName.IsPhysical())
bindingSignature.SetAccessModifier(implAccessRights)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes

open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
open JetBrains.ReSharper.Psi
open JetBrains.ReSharper.Resources.Shell
open JetBrains.ReSharper.Plugins.FSharp.Psi

type UpdateAccessibilityInSignatureMemberFix(error: ValueNotContainedMutabilityAccessibilityMoreInMemberError) =
inherit FSharpQuickFixBase()

let tryFindSignatureMemberAccessRights (memberDeclaration: IOverridableMemberDeclaration) =
if isNull memberDeclaration.DeclaredElement then None else
memberDeclaration.DeclaredElement.GetDeclarations()
|> Seq.tryPick (function
| :? IMemberSignature as memberSig -> Some (memberSig, memberSig.GetAccessRights())
| _ -> None)
let mutable implAccessRights = AccessRights.NONE
let mutable memberSignature = null

override x.Text = $"Update accessibility for {error.MemberDeclaration.Identifier.GetText()} in signature"

override x.IsAvailable _ =
if isNull error.MemberDeclaration then false else
implAccessRights <- error.MemberDeclaration.GetAccessRights()

match tryFindSignatureMemberAccessRights error.MemberDeclaration with
| None -> false
| Some (ms, sigAccessRights) ->
memberSignature <- ms
implAccessRights <> sigAccessRights

override x.ExecutePsiTransaction _ =
use writeCookie = WriteLockCookie.Create(error.MemberDeclaration.IsPhysical())
memberSignature.SetAccessModifier(implAccessRights)
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,28 @@
<QuickFix>UpdateMutabilityInSignatureFix</QuickFix>
</Error>

<Error staticGroup="FSharpErrors" name="ValueNotContainedMutabilityAccessibilityMoreInBinding" ID="FS0034: Module contains but its signature specifies The accessibility specified in the signature is more than that specified in the implementation">
<Parameter type="IExpressionReferenceName" name="referenceName"/>
<Parameter type="string" name="fcsMessage"/>
<Range>referenceName.GetNavigationRange()</Range>
<Message resourceName="Message" resourceType="Strings">
<Argument>fcsMessage</Argument>
</Message>
<Behavour overlapResolvePolicy="NONE"/>
<QuickFix>UpdateAccessibilityInSignatureBindingFix</QuickFix>
</Error>

<Error staticGroup="FSharpErrors" name="ValueNotContainedMutabilityAccessibilityMoreInMember" ID="FS0034: Module contains but its signature specifies The accessibility specified in the signature is more than that specified in the implementation">
<Parameter type="IOverridableMemberDeclaration" name="memberDeclaration"/>
<Parameter type="string" name="fcsMessage"/>
<Range>memberDeclaration.GetNavigationRange()</Range>
<Message resourceName="Message" resourceType="Strings">
<Argument>fcsMessage</Argument>
</Message>
<Behavour overlapResolvePolicy="NONE"/>
<QuickFix>UpdateAccessibilityInSignatureMemberFix</QuickFix>
</Error>

<Error staticGroup="FSharpErrors" name="VarBoundTwice" ID="FS0038: Pattern bound twice">
<Parameter type="IReferencePat" name="pat"/>
<Message resourceName="IsBoundMultipleTimesMessage" resourceType="Strings">
Expand Down
3 changes: 3 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/FSharp.psi
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,7 @@ memberSignature options { stubBase="FSharpProperTypeMemberDeclarationBase"; } e
attributeList<ATTRIBUTE_LIST, AttributeLists>*
STATIC<STATIC, StaticKeyword>?
memberKeyword{MEMBER_KEYWORD, MemberKeyword}
INLINE<INLINE, InlineKeyword>?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessModifier{ACCESS_MODIFIER, AccessModifier}?
identOrOpName{IDENTIFIER, Identifier}
postfixTypeParameterDeclarationList<TYPE_PARAMETER_LIST, TypeParameterList>?
Expand Down Expand Up @@ -1369,6 +1370,8 @@ autoPropertyDeclaration options { stubBase="FSharpProperTypeMemberDeclarationBas
STATIC<STATIC, StaticKeyword>?
memberKeyword{MEMBER, MemberKeyword}
VAL<VAL, ValKeyword>
MUTABLE<MUTABLE, MutableKeyword>?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessModifier{ACCESS_MODIFIER, AccessModifier}?
IDENTIFIER<IDENTIFIER, Identifier>
EQUALS<FSHARP_EQUALS, EqualsToken>
chameleonExpression<CHAMELEON_EXPR, InitExpression>
Expand Down
11 changes: 11 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Impl/ModifiersUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Caches2;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;
using JetBrains.ReSharper.Psi.Tree;

namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl
Expand Down Expand Up @@ -121,5 +122,15 @@ public static AccessRights GetAccessRights([CanBeNull] ITokenNode accessModifier

return AccessRights.PUBLIC;
}

public static ITreeNode GetAccessNode(AccessRights accessRights)
{
return accessRights switch
{
AccessRights.PRIVATE => FSharpTokenType.PRIVATE.CreateTreeElement(),
AccessRights.INTERNAL => FSharpTokenType.INTERNAL.CreateTreeElement(),
_ => FSharpTokenType.PUBLIC.CreateTreeElement()
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ protected override IDeclaredElement CreateDeclaredElement(FSharpSymbol fcsSymbol

public override bool IsOverride => this.IsOverride();
public override bool IsExplicitImplementation => this.IsExplicitImplementation();
public override AccessRights GetAccessRights() => ModifiersUtil.GetAccessRights(AccessModifier);
}
}
14 changes: 14 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Impl/Tree/BindingSignature.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;

namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
Expand All @@ -22,5 +23,18 @@ public void SetIsMutable(bool value)
if (headPat != null)
FSharpImplUtil.AddTokenBefore(headPat, FSharpTokenType.MUTABLE);
}

public void SetAccessModifier(AccessRights accessModifier)
{
// TODO: check for AccessRights.NONE
if (AccessModifier == null)
{
ModificationUtil.AddChildAfter(BindingKeyword, ModifiersUtil.GetAccessNode(accessModifier));
}
else
{
ModificationUtil.ReplaceChild(AccessModifier, ModifiersUtil.GetAccessNode(accessModifier));
}
}
}
}
12 changes: 12 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Impl/Tree/MemberSignature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;

namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
{
Expand All @@ -27,6 +28,17 @@ protected override IDeclaredElement CreateDeclaredElement(FSharpSymbol fcsSymbol
this.CreateMemberDeclaredElement(fcsSymbol);

public bool IsIndexer => this.IsIndexer();
public void SetAccessModifier(AccessRights accessModifier)
{
if (AccessModifier == null)
{
ModificationUtil.AddChildAfter(InlineKeyword ?? MemberKeyword, ModifiersUtil.GetAccessNode(accessModifier));
}
else
{
ModificationUtil.ReplaceChild(AccessModifier, ModifiersUtil.GetAccessNode(accessModifier));
}
}

public override bool IsStatic => StaticKeyword != null;
public override bool IsVirtual => MemberKeyword?.GetTokenType() == FSharpTokenType.DEFAULT;
Expand Down
9 changes: 9 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Tree/IBindingSignature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using JetBrains.ReSharper.Psi;

namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
{
public partial interface IBindingSignature
{
void SetAccessModifier(AccessRights accessModifier);
}
}
9 changes: 9 additions & 0 deletions ReSharper.FSharp/src/FSharp.Psi/src/Tree/IMemberSignature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using JetBrains.ReSharper.Psi;

namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
{
public partial interface IMemberSignature
{
void SetAccessModifier(AccessRights accessModifier);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let private a{caret} = 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let private a{caret} = 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val internal a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val private a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let internal a{caret} = 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let internal a{caret} = 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val internal a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let inline private a{caret} b = ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let inline private a{caret} b = ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val inline public a: b: 't -> unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val inline private a: b: 't -> unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let mutable private a{caret} = 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

let mutable private a{caret} = 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val mutable public a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module A

val mutable private a: int
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
member val private Foo{caret} = 1 with get,set
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
member val private Foo{caret} = 1 with get,set
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
member Foo: int with get,set
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
member private Foo: int with get,set
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
member private this.Foo{caret}() = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
member private this.Foo{caret}() = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
member internal Foo: unit -> int
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
member private Foo: unit -> int
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
static member private Foo{caret}() = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
static member private Foo{caret}() = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
static member public Foo: unit -> int
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module A

type B =
new: unit -> B
static member private Foo: unit -> int
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
static member inline private Foo{caret}() = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module A

type B() =
static member inline private Foo{caret}() = 1
Loading