Skip to content
Browse files

CLJ-1363 - reflect .- should return field if both field and method exist

  • Loading branch information...
1 parent 3b1a1dd commit 5fda6cb262d1807566ecadd3af9aaafb58ee5544 @puredanger puredanger committed with Stuart Halloway Feb 27, 2014
View
11 src/jvm/clojure/lang/Compiler.java
@@ -943,7 +943,7 @@ else if(instance != null && instance.hasJavaClass() && instance.getJavaClass() !
if(c != null) {
return new StaticFieldExpr(line, column, c, munge(sym.name), tag);
} else
- return new InstanceFieldExpr(line, column, instance, munge(sym.name), tag);
+ return new InstanceFieldExpr(line, column, instance, munge(sym.name), tag, (((Symbol)RT.third(form)).name.charAt(0) == '-'));
}
else
{
@@ -1081,18 +1081,20 @@ else if(sym.name.equals("boolean"))
public final int line;
public final int column;
public final Symbol tag;
- final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String)");
+ public final boolean requireField;
+ final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String,boolean)");
final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)");
- public InstanceFieldExpr(int line, int column, Expr target, String fieldName, Symbol tag) {
+ public InstanceFieldExpr(int line, int column, Expr target, String fieldName, Symbol tag, boolean requireField) {
this.target = target;
this.targetClass = target.hasJavaClass() ? target.getJavaClass() : null;
this.field = targetClass != null ? Reflector.getField(targetClass, fieldName, false) : null;
this.fieldName = fieldName;
this.line = line;
this.column = column;
this.tag = tag;
+ this.requireField = requireField;
if(field == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
{
if(targetClass == null)
@@ -1111,7 +1113,7 @@ public InstanceFieldExpr(int line, int column, Expr target, String fieldName, Sy
}
public Object eval() {
- return Reflector.invokeNoArgInstanceMember(target.eval(), fieldName);
+ return Reflector.invokeNoArgInstanceMember(target.eval(), fieldName, requireField);
}
public boolean canEmitPrimitive(){
@@ -1149,6 +1151,7 @@ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
{
target.emit(C.EXPRESSION, objx, gen);
gen.push(fieldName);
+ gen.push(requireField);
gen.invokeStatic(REFLECTOR_TYPE, invokeNoArgInstanceMember);
if(context == C.STATEMENT)
gen.pop();
View
28 src/jvm/clojure/lang/Reflector.java
@@ -291,13 +291,29 @@ public static Object setInstanceField(Object target, String fieldName, Object va
+ " for " + target.getClass());
}
+// not used as of Clojure 1.6, but left for runtime compatibility with
+// compiled bytecode from older versions
public static Object invokeNoArgInstanceMember(Object target, String name) {
- //favor method over field
- List meths = getMethods(target.getClass(), 0, name, false);
- if(meths.size() > 0)
- return invokeMatchingMethod(name, meths, target, RT.EMPTY_ARRAY);
- else
- return getInstanceField(target, name);
+ return invokeNoArgInstanceMember(target, name, false);
+}
+
+public static Object invokeNoArgInstanceMember(Object target, String name, boolean requireField) {
+ Class c = target.getClass();
+
+ if(requireField) {
+ Field f = getField(c, name, false);
+ if(f != null)
+ return getInstanceField(target, name);
+ else
+ throw new IllegalArgumentException("No matching field found: " + name
+ + " for " + target.getClass());
+ } else {
+ List meths = getMethods(c, 0, name, false);
+ if(meths.size() > 0)
+ return invokeMatchingMethod(name, meths, target, RT.EMPTY_ARRAY);
+ else
+ return getInstanceField(target, name);
+ }
}
public static Object invokeInstanceMember(Object target, String name) {
View
10 test/clojure/test_clojure/java_interop.clj
@@ -55,6 +55,16 @@
Integer/MAX_VALUE
(. Integer MAX_VALUE) ))
+(definterface I (a []))
+(deftype T [a] I (a [_] "method"))
+
+(deftest test-reflective-field-name-ambiguous
+ (let [t (->T "field")]
+ (is (= "method" (. ^T t a)))
+ (is (= "field" (. ^T t -a)))
+ (is (= "method" (. t a)))
+ (is (= "field" (. t -a)))
+ (is (thrown? IllegalArgumentException (. t -BOGUS)))))
(deftest test-double-dot
(is (= (.. System (getProperties) (get "os.name"))

0 comments on commit 5fda6cb

Please sign in to comment.
Something went wrong with that request. Please try again.