1
1
package org .mockito
2
2
3
- import java .lang .reflect .{ Field , Method , Modifier }
4
-
5
- import org .mockito .internal .ValueClassWrapper
3
+ import org .mockito .JavaReflectionUtils .resolveWithJavaGenerics
6
4
import org .mockito .invocation .InvocationOnMock
7
5
import org .scalactic .TripleEquals ._
8
- import ru .vyarus .java .generics .resolver .GenericsResolver
9
6
7
+ import java .lang .reflect .Method
10
8
import scala .reflect .ClassTag
11
9
import scala .reflect .internal .Symbols
12
10
import scala .util .{ Try => uTry }
13
- import scala .util .control .NonFatal
14
11
15
12
object ReflectionUtils {
16
13
import scala .reflect .runtime .{ universe => ru }
@@ -23,58 +20,37 @@ object ReflectionUtils {
23
20
def methodToJava (sym : Symbols # MethodSymbol ): Method
24
21
}]
25
22
26
- def listToTuple (l : List [Object ]): Any =
27
- l match {
28
- case Nil => Nil
29
- case h :: Nil => h
30
- case _ => Class .forName(s " scala.Tuple ${l.size}" ).getDeclaredConstructors.head.newInstance(l : _* )
31
- }
32
-
33
- implicit class InvocationOnMockOps (val invocation : InvocationOnMock ) extends AnyVal {
34
- def mock [M ]: M = invocation.getMock.asInstanceOf [M ]
35
- def method : Method = invocation.getMethod
36
- def arg [A : ValueClassWrapper ](index : Int ): A = ValueClassWrapper [A ].wrapAs[A ](invocation.getArgument(index))
37
- def args : List [Any ] = invocation.getArguments.toList
38
- def callRealMethod [R ](): R = invocation.callRealMethod.asInstanceOf [R ]
39
- def argsAsTuple : Any = listToTuple(args.map(_.asInstanceOf [Object ]))
40
-
41
- def returnType : Class [_] = {
42
- val javaReturnType = method.getReturnType
23
+ private [mockito] def returnType (invocation : InvocationOnMock ): Class [_] = {
24
+ val javaReturnType = invocation.method.getReturnType
43
25
44
- if (javaReturnType == classOf [Object ])
45
- resolveWithScalaGenerics
46
- .orElse(resolveWithJavaGenerics)
47
- .getOrElse(javaReturnType)
48
- else javaReturnType
49
- }
26
+ if (javaReturnType == classOf [Object ])
27
+ resolveWithScalaGenerics(invocation)
28
+ .orElse(resolveWithJavaGenerics(invocation) )
29
+ .getOrElse(javaReturnType)
30
+ else javaReturnType
31
+ }
50
32
51
- def returnsValueClass : Boolean = findTypeSymbol.exists(_.returnType.typeSymbol.isDerivedValueClass)
33
+ private [mockito] def returnsValueClass (invocation : InvocationOnMock ): Boolean =
34
+ findTypeSymbol(invocation).exists(_.returnType.typeSymbol.isDerivedValueClass)
52
35
53
- private def resolveWithScalaGenerics : Option [Class [_]] =
54
- uTry {
55
- findTypeSymbol
56
- .filter(_.returnType.typeSymbol.isClass)
57
- .map(_.asMethod.returnType.typeSymbol.asClass)
58
- .map(mirror.runtimeClass)
59
- }.toOption.flatten
60
-
61
- private def findTypeSymbol =
62
- uTry {
63
- mirror
64
- .classSymbol(method.getDeclaringClass)
65
- .info
66
- .decls
67
- .collectFirst {
68
- case symbol if isNonConstructorMethod(symbol) && customMirror.methodToJava(symbol) === method => symbol
69
- }
70
- }.toOption.flatten
36
+ private def resolveWithScalaGenerics (invocation : InvocationOnMock ): Option [Class [_]] =
37
+ uTry {
38
+ findTypeSymbol(invocation)
39
+ .filter(_.returnType.typeSymbol.isClass)
40
+ .map(_.asMethod.returnType.typeSymbol.asClass)
41
+ .map(mirror.runtimeClass)
42
+ }.toOption.flatten
71
43
72
- private def resolveWithJavaGenerics : Option [Class [_]] =
73
- try Some (GenericsResolver .resolve(invocation.getMock.getClass).`type`(method.getDeclaringClass).method(method).resolveReturnClass())
74
- catch {
75
- case _ : Throwable => None
76
- }
77
- }
44
+ private def findTypeSymbol (invocation : InvocationOnMock ) =
45
+ uTry {
46
+ mirror
47
+ .classSymbol(invocation.method.getDeclaringClass)
48
+ .info
49
+ .decls
50
+ .collectFirst {
51
+ case symbol if isNonConstructorMethod(symbol) && customMirror.methodToJava(symbol) === invocation.method => symbol
52
+ }
53
+ }.toOption.flatten
78
54
79
55
private def isNonConstructorMethod (d : ru.Symbol ): Boolean = d.isMethod && ! d.isConstructor
80
56
@@ -113,37 +89,4 @@ object ReflectionUtils {
113
89
.getOrElse(Seq .empty)
114
90
}
115
91
116
- def setFinalStatic (field : Field , newValue : AnyRef ): Unit =
117
- try {
118
- // Try to get Unsafe instance (works with both sun.misc.Unsafe and jdk.internal.misc.Unsafe)
119
- val unsafeClass : Class [_] =
120
- try
121
- Class .forName(" sun.misc.Unsafe" )
122
- catch {
123
- case _ : ClassNotFoundException => Class .forName(" jdk.internal.misc.Unsafe" )
124
- }
125
-
126
- val unsafeField = unsafeClass.getDeclaredField(" theUnsafe" )
127
- unsafeField.setAccessible(true )
128
- val unsafe = unsafeField.get(null )
129
-
130
- // Get methods via reflection to handle both Unsafe implementations
131
- val staticFieldBaseMethod = unsafeClass.getMethod(" staticFieldBase" , classOf [Field ])
132
- val staticFieldOffsetMethod = unsafeClass.getMethod(" staticFieldOffset" , classOf [Field ])
133
- val putObjectMethod = unsafeClass.getMethod(" putObject" , classOf [Object ], classOf [Long ], classOf [Object ])
134
-
135
- // Make the field accessible
136
- field.setAccessible(true )
137
-
138
- // Get base and offset for the field
139
- val base : Object = staticFieldBaseMethod.invoke(unsafe, field)
140
- val offset : Long = staticFieldOffsetMethod.invoke(unsafe, field).asInstanceOf [Long ]
141
-
142
- // Set the field value directly
143
- putObjectMethod.invoke(unsafe, base, java.lang.Long .valueOf(offset), newValue)
144
- } catch {
145
- case NonFatal (e) =>
146
- throw new IllegalStateException (s " Cannot modify final field ${field.getName}" , e)
147
- }
148
-
149
92
}
0 commit comments