Skip to content

Commit e8fc421

Browse files
qerubstuarthalloway
authored andcommitted
CLJ-1248 - Include type information in reflection warning messages
Signed-off-by: Stuart Halloway <stu@cognitect.com>
1 parent 762db74 commit e8fc421

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed

src/jvm/clojure/lang/Compiler.java

+46-12
Original file line numberDiff line numberDiff line change
@@ -1095,9 +1095,18 @@ public InstanceFieldExpr(int line, int column, Expr target, String fieldName, Sy
10951095
this.tag = tag;
10961096
if(field == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
10971097
{
1098-
RT.errPrintWriter()
1099-
.format("Reflection warning, %s:%d:%d - reference to field %s can't be resolved.\n",
1100-
SOURCE_PATH.deref(), line, column, fieldName);
1098+
if(targetClass == null)
1099+
{
1100+
RT.errPrintWriter()
1101+
.format("Reflection warning, %s:%d:%d - reference to field %s can't be resolved.\n",
1102+
SOURCE_PATH.deref(), line, column, fieldName);
1103+
}
1104+
else
1105+
{
1106+
RT.errPrintWriter()
1107+
.format("Reflection warning, %s:%d:%d - reference to field %s on %s can't be resolved.\n",
1108+
SOURCE_PATH.deref(), line, column, fieldName, targetClass.getName());
1109+
}
11011110
}
11021111
}
11031112

@@ -1396,8 +1405,15 @@ public InstanceMethodExpr(String source, int line, int column, Symbol tag, Expr
13961405
{
13971406
List methods = Reflector.getMethods(target.getJavaClass(), args.count(), methodName, false);
13981407
if(methods.isEmpty())
1408+
{
13991409
method = null;
1400-
//throw new IllegalArgumentException("No matching method found");
1410+
if(RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
1411+
{
1412+
RT.errPrintWriter()
1413+
.format("Reflection warning, %s:%d:%d - call to method %s on %s can't be resolved (no such method).\n",
1414+
SOURCE_PATH.deref(), line, column, methodName, target.getJavaClass().getName());
1415+
}
1416+
}
14011417
else
14021418
{
14031419
int methodidx = 0;
@@ -1421,16 +1437,23 @@ public InstanceMethodExpr(String source, int line, int column, Symbol tag, Expr
14211437
m = Reflector.getAsMethodOfPublicBase(m.getDeclaringClass(), m);
14221438
}
14231439
method = m;
1440+
if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
1441+
{
1442+
RT.errPrintWriter()
1443+
.format("Reflection warning, %s:%d:%d - call to method %s on %s can't be resolved (argument types: %s).\n",
1444+
SOURCE_PATH.deref(), line, column, methodName, target.getJavaClass().getName(), getTypeStringForArgs(args));
1445+
}
14241446
}
14251447
}
14261448
else
1427-
method = null;
1428-
1429-
if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
14301449
{
1431-
RT.errPrintWriter()
1432-
.format("Reflection warning, %s:%d:%d - call to %s can't be resolved.\n",
1433-
SOURCE_PATH.deref(), line, column, methodName);
1450+
method = null;
1451+
if(RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
1452+
{
1453+
RT.errPrintWriter()
1454+
.format("Reflection warning, %s:%d:%d - call to method %s can't be resolved (target class is unknown).\n",
1455+
SOURCE_PATH.deref(), line, column, methodName);
1456+
}
14341457
}
14351458
}
14361459

@@ -1580,8 +1603,8 @@ public StaticMethodExpr(String source, int line, int column, Symbol tag, Class c
15801603
if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
15811604
{
15821605
RT.errPrintWriter()
1583-
.format("Reflection warning, %s:%d:%d - call to %s can't be resolved.\n",
1584-
SOURCE_PATH.deref(), line, column, methodName);
1606+
.format("Reflection warning, %s:%d:%d - call to static method %s on %s can't be resolved (argument types: %s).\n",
1607+
SOURCE_PATH.deref(), line, column, methodName, c.getName(), getTypeStringForArgs(args));
15851608
}
15861609
}
15871610

@@ -2328,6 +2351,17 @@ static public boolean subsumes(Class[] c1, Class[] c2){
23282351
return better;
23292352
}
23302353

2354+
static String getTypeStringForArgs(IPersistentVector args){
2355+
StringBuilder sb = new StringBuilder();
2356+
for(int i = 0; i < args.count(); i++)
2357+
{
2358+
Expr arg = (Expr) args.nth(i);
2359+
if (i > 0) sb.append(", ");
2360+
sb.append(arg.hasJavaClass() ? arg.getJavaClass().getName() : "unknown");
2361+
}
2362+
return sb.toString();
2363+
}
2364+
23312365
static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, IPersistentVector argexprs,
23322366
List<Class> rets)
23332367
{

test/clojure/test_clojure/rt.clj

+20-4
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,33 @@
3535
(should-print-err-message
3636
#"Reflection warning, .*:\d+:\d+ - reference to field blah can't be resolved\.\r?\n"
3737
(defn foo [x] (.blah x))))
38-
(testing "reflection cannot resolve instance method"
38+
(testing "reflection cannot resolve field on known class"
3939
(should-print-err-message
40-
#"Reflection warning, .*:\d+:\d+ - call to zap can't be resolved\.\r?\n"
40+
#"Reflection warning, .*:\d+:\d+ - reference to field blah on java\.lang\.String can't be resolved\.\r?\n"
41+
(defn foo [^String x] (.blah x))))
42+
(testing "reflection cannot resolve instance method because it is missing"
43+
(should-print-err-message
44+
#"Reflection warning, .*:\d+:\d+ - call to method zap on java\.lang\.String can't be resolved \(no such method\)\.\r?\n"
45+
(defn foo [^String x] (.zap x 1))))
46+
(testing "reflection cannot resolve instance method because it has incompatible argument types"
47+
(should-print-err-message
48+
#"Reflection warning, .*:\d+:\d+ - call to method getBytes on java\.lang\.String can't be resolved \(argument types: java\.util\.regex\.Pattern\)\.\r?\n"
49+
(defn foo [^String x] (.getBytes x #"boom"))))
50+
(testing "reflection cannot resolve instance method because it has unknown argument types"
51+
(should-print-err-message
52+
#"Reflection warning, .*:\d+:\d+ - call to method getBytes on java\.lang\.String can't be resolved \(argument types: unknown\)\.\r?\n"
53+
(defn foo [^String x y] (.getBytes x y))))
54+
(testing "reflection cannot resolve instance method because target class is unknown"
55+
(should-print-err-message
56+
#"Reflection warning, .*:\d+:\d+ - call to method zap can't be resolved \(target class is unknown\)\.\r?\n"
4157
(defn foo [x] (.zap x 1))))
4258
(testing "reflection cannot resolve static method"
4359
(should-print-err-message
44-
#"Reflection warning, .*:\d+:\d+ - call to valueOf can't be resolved\.\r?\n"
60+
#"Reflection warning, .*:\d+:\d+ - call to static method valueOf on java\.lang\.Integer can't be resolved \(argument types: java\.util\.regex\.Pattern\)\.\r?\n"
4561
(defn foo [] (Integer/valueOf #"boom"))))
4662
(testing "reflection cannot resolve constructor"
4763
(should-print-err-message
48-
#"Reflection warning, .*:\d+:\d+ - call to java.lang.String ctor can't be resolved\.\r?\n"
64+
#"Reflection warning, .*:\d+:\d+ - call to java\.lang\.String ctor can't be resolved\.\r?\n"
4965
(defn foo [] (String. 1 2 3)))))
5066

5167
(def example-var)

0 commit comments

Comments
 (0)