Skip to content

Commit 1bd0c19

Browse files
auduchinokintellij-monorepo-bot
authored andcommitted
RIDER-134148 Fix broken abstract/virtual calculation for generic members
GitOrigin-RevId: c5bbfbce25767ba8b9801894be86e1b5de6bb034
1 parent b06ffe4 commit 1bd0c19

File tree

5 files changed

+185
-8
lines changed

5 files changed

+185
-8
lines changed

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Impl/Tree/AbstractMemberDeclaration.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using JetBrains.ReSharper.Plugins.FSharp.Psi.Util;
99
using JetBrains.ReSharper.Plugins.FSharp.Util;
1010
using JetBrains.ReSharper.Psi;
11+
using JetBrains.Util;
1112

1213
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
1314
{
@@ -36,23 +37,21 @@ public bool HasDefaultImplementation
3637

3738
private static bool CalcHasDefaultImplementation([CanBeNull] FSharpMemberOrFunctionOrValue mfv)
3839
{
39-
if (mfv is not {IsDispatchSlot: true})
40+
if (mfv is not { IsDispatchSlot: true })
4041
return false;
4142

42-
var mfvEntity = mfv.DeclaringEntity;
43+
var mfvEntity = mfv.DeclaringEntity?.Value;
4344
if (mfvEntity == null)
4445
return false;
4546

4647
var logicalName = mfv.LogicalName;
47-
var mfvType = mfv.FullType.GenericArguments[1];
4848

49-
return mfvEntity.Value.MembersFunctionsAndValues.Any(m =>
49+
return mfvEntity.MembersFunctionsAndValues.Any(m =>
5050
m.IsOverrideOrExplicitInterfaceImplementation &&
5151
logicalName == m.LogicalName &&
52-
(m.XmlDocSig == mfv.XmlDocSig && m.ImplementedAbstractSignatures.Count == 0 ||
53-
mfvType.Equals(m.FullType) &&
54-
m.ImplementedAbstractSignatures.Count == 1 &&
55-
m.ImplementedAbstractSignatures[0].DeclaringType.Equals(mfvEntity.Value.AsType())));
52+
m.XmlDocSig == mfv.XmlDocSig &&
53+
m.ImplementedAbstractSignatures.SingleItem() is { DeclaringType: { HasTypeDefinition: true } declaringType } &&
54+
declaringType.TypeDefinition.Equals(mfvEntity));
5655
}
5756

5857
protected override string DeclaredElementName => NameIdentifier.GetCompiledName(Attributes);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
public class InheritAbstractClass : Module.AbstractClass;
2+
3+
public class InheritAbstractClassOverrides : Module.AbstractClass
4+
{
5+
public override void M1() => base.M1();
6+
public override void M2(int i) => base.M2(i);
7+
public override void M3<P1>(int i) => base.M3<P1>(i);
8+
public override void M4<P1>(P1 p1) => base.M4(p1);
9+
public override int P1 { get; }
10+
}
11+
12+
public class InheritGenericAbstract : Module.GenericAbstractClass<int>;
13+
14+
public class InheritGenericAbstractOverrides : Module.GenericAbstractClass<int>
15+
{
16+
public override void M1() => base.M1();
17+
public override void M2(int i) => base.M2(i);
18+
public override void M3<P1>(int i) => base.M3<P1>(i);
19+
public override void M4<P1>(P1 p1) => base.M4(p1);
20+
public override void M5<P1>(P1 p1, int i) => base.M5<P1>(p1, i);
21+
public override int P1 { get; }
22+
}
23+
24+
public class InheritGeneric : Module.GenericClass<int>;
25+
26+
public class InheritGenericOverrides : Module.GenericClass<int>
27+
{
28+
public override void M() => base.M();
29+
public override void M2(int i) => base.M2(i);
30+
public override void M3<P1>(int i) => base.M3<P1>(i);
31+
public override void M4(int i) => base.M4(i);
32+
public override void M5<P1>(P1 p1, int i) => base.M5<P1>(p1, i);
33+
}
34+
35+
public sealed class Counter;
36+
public sealed class CounterState;
37+
38+
public class InheritGenericCommand2 : Module.GenericAbstractClass2<Counter, CounterState, bool, int>;
39+
40+
public class InheritGenericCommand2Overrides : Module.GenericAbstractClass2<Counter, CounterState, bool, int>
41+
{
42+
public override bool M(CounterState state, bool input) => base.M(state, input);
43+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
module Module
2+
3+
[<AbstractClass>]
4+
type AbstractClass() =
5+
abstract member M1: unit -> unit
6+
default this.M1() = ()
7+
8+
abstract member M2: int -> unit
9+
default this.M2(i: int) = ()
10+
11+
abstract member M3<'P1>: int -> unit
12+
default this.M3<'P1>(i: int) = ()
13+
14+
abstract member M4: 'P1 -> unit
15+
default this.M4(p: 'P1) = ()
16+
17+
abstract member P1: int
18+
default this.P1 = 1
19+
20+
[<AbstractClass>]
21+
type GenericAbstractClass<'TOuter>() =
22+
abstract member M1: unit -> unit
23+
default this.M1() = ()
24+
25+
abstract member M2: int -> unit
26+
default this.M2(i: int) = ()
27+
28+
abstract member M3<'P1>: int -> unit
29+
default this.M3<'P1>(i: int) = ()
30+
31+
abstract member M4<'P1>: 'P1 -> unit
32+
default this.M4<'P1>(i: 'P1) = ()
33+
34+
abstract member M5<'P1>: 'P1 * 'TOuter -> unit
35+
default this.M5<'P1>(i1: 'P1, i2: 'TOuter) = ()
36+
37+
abstract member P1: 'TOuter
38+
default this.P1 = Unchecked.defaultof<'TOuter>
39+
40+
[<AbstractClass>]
41+
type GenericAbstractClass2<'TSystem, 'TState, 'TInput, 'TOutput>() =
42+
abstract member M: state: 'TState * input: 'TInput -> bool
43+
default this.M(_, _) = true
44+
45+
type GenericClass<'TOuter>() =
46+
abstract member M: unit -> unit
47+
default this.M() = ()
48+
49+
abstract member M2: int -> unit
50+
default this.M2(i: int) = ()
51+
52+
abstract member M3<'P1>: int -> unit
53+
default this.M3<'P1>(i: int) = ()
54+
55+
abstract member M4: 'TOuter -> unit
56+
default this.M4(p: 'TOuter) = ()
57+
58+
abstract member M5<'P1>: 'P1 * 'TOuter -> unit
59+
default this.M5<'P1>(i1: 'P1, i2: 'TOuter) = ()
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
public class InheritAbstractClass : Module.AbstractClass;
2+
3+
public class InheritAbstractClassOverrides : Module.AbstractClass
4+
{
5+
public override void M1() => base.M1();
6+
public override void M2(int i) => base.M2(i);
7+
public override void M3<P1>(int i) => base.M3<P1>(i);
8+
public override void M4<P1>(P1 p1) => base.M4(p1);
9+
public override int P1 { get; }
10+
}
11+
12+
public class InheritGenericAbstract : Module.GenericAbstractClass<int>;
13+
14+
public class InheritGenericAbstractOverrides : Module.GenericAbstractClass<int>
15+
{
16+
public override void M1() => base.M1();
17+
public override void M2(int i) => base.M2(i);
18+
public override void M3<P1>(int i) => base.M3<P1>(i);
19+
public override void M4<P1>(P1 p1) => base.M4(p1);
20+
public override void M5<P1>(P1 p1, int i) => base.M5<P1>(p1, i);
21+
public override int P1 { get; }
22+
}
23+
24+
public class InheritGeneric : Module.GenericClass<int>;
25+
26+
public class InheritGenericOverrides : Module.GenericClass<int>
27+
{
28+
public override void M() => base.M();
29+
public override void M2(int i) => base.M2(i);
30+
public override void M3<P1>(int i) => base.M3<P1>(i);
31+
public override void M4(int i) => base.M4(i);
32+
public override void M5<P1>(P1 p1, int i) => base.M5<P1>(p1, i);
33+
}
34+
35+
public sealed class Counter;
36+
public sealed class CounterState;
37+
38+
public class InheritGenericCommand2 : Module.GenericAbstractClass2<Counter, CounterState, bool, int>;
39+
40+
public class InheritGenericCommand2Overrides : Module.GenericAbstractClass2<Counter, CounterState, bool, int>
41+
{
42+
public override bool M(CounterState state, bool input) => base.M(state, input);
43+
}
44+
45+
---------------------------------------------------------
46+
M:Module.AbstractClass.M1
47+
M:Module.AbstractClass.M1
48+
M:Module.AbstractClass.M2(System.Int32)
49+
M:Module.AbstractClass.M2(System.Int32)
50+
M:Module.AbstractClass.M3``1(System.Int32)
51+
M:Module.AbstractClass.M3``1(System.Int32)
52+
M:Module.AbstractClass.M4``1(`0)
53+
M:Module.AbstractClass.M4``1(`0)
54+
M:Module.GenericAbstractClass`1.M1
55+
M:Module.GenericAbstractClass`1.M1
56+
M:Module.GenericAbstractClass`1.M2(System.Int32)
57+
M:Module.GenericAbstractClass`1.M2(System.Int32)
58+
M:Module.GenericAbstractClass`1.M3``1(System.Int32)
59+
M:Module.GenericAbstractClass`1.M3``1(System.Int32)
60+
M:Module.GenericAbstractClass`1.M4``1(`0)
61+
M:Module.GenericAbstractClass`1.M4``1(`0)
62+
M:Module.GenericAbstractClass`1.M5``1(`0,`0)
63+
M:Module.GenericAbstractClass`1.M5``1(`0,`0)
64+
M:Module.GenericClass`1.M
65+
M:Module.GenericClass`1.M
66+
M:Module.GenericClass`1.M2(System.Int32)
67+
M:Module.GenericClass`1.M2(System.Int32)
68+
M:Module.GenericClass`1.M3``1(System.Int32)
69+
M:Module.GenericClass`1.M3``1(System.Int32)
70+
M:Module.GenericClass`1.M4(`0)
71+
M:Module.GenericClass`1.M4(`0)
72+
M:Module.GenericClass`1.M5``1(`0,`0)
73+
M:Module.GenericClass`1.M5``1(`0,`0)
74+
M:Module.GenericAbstractClass2`4.M(`1,`2)
75+
M:Module.GenericAbstractClass2`4.M(`1,`2)

ReSharper.FSharp/test/src/FSharp.Tests/Cache/CSharpResolveTest.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type CSharpResolveTest() =
7474
[<Test>] member x.``Auto properties 02, compiled name``() = x.DoNamedTest()
7575

7676
[<Test>] member x.``Members 01 - Virtual``() = x.DoNamedTest()
77+
[<Test>] member x.``Members 02 - Virtual``() = x.DoNamedTest()
7778

7879
[<Test>] member x.``Methods 01``() = x.DoNamedTest()
7980
[<Test>] member x.``Methods 02, compiled name``() = x.DoNamedTest()

0 commit comments

Comments
 (0)