-
Notifications
You must be signed in to change notification settings - Fork 194
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
Wrong detection of field vs setter access within closure #366
Comments
Implemented in this method in SimpleTypeLookup. Accessors are passed up when static does not match but fields and properties are not checked the same. Probably should be checking against isStaticExpression all the way through. protected ASTNode findDeclaration(String name, ClassNode declaringType, boolean isLhsExpression, boolean isStaticExpression, List<ClassNode> methodCallArgumentTypes) {
if (declaringType.isArray()) {
// only length exists on arrays
if (name.equals("length")) {
return createLengthField(declaringType);
}
// otherwise search on object
return findDeclaration(name, VariableScope.OBJECT_CLASS_NODE, isLhsExpression, isStaticExpression, methodCallArgumentTypes);
}
if (methodCallArgumentTypes != null) {
ASTNode method = findMethodDeclaration(name, declaringType, methodCallArgumentTypes);
if (method != null) {
return method;
}
// name may still map to something that is callable; keep looking
}
// look for canonical accessor method
MethodNode accessor = AccessorSupport.findAccessorMethodForPropertyName(name, declaringType, false, !isLhsExpression ? READER : WRITER);
if (accessor != null && !isSynthetic(accessor) && (accessor.isStatic() == isStaticExpression)) {
return accessor;
}
LinkedHashSet<ClassNode> typeHierarchy = new LinkedHashSet<ClassNode>();
VariableScope.createTypeHierarchy(declaringType, typeHierarchy, true);
// look for property
for (ClassNode type : typeHierarchy) {
PropertyNode property = type.getProperty(name);
if (property != null && (property.isStatic() == isStaticExpression)) {
return property;
}
}
// look for field
FieldNode field = declaringType.getField(name);
if (field != null && (field.isStatic() == isStaticExpression)) {
return field;
}
typeHierarchy.clear();
VariableScope.findAllInterfaces(declaringType, typeHierarchy, true);
// look for constant in interfaces
for (ClassNode type : typeHierarchy) {
if (type == declaringType) {
continue;
}
field = type.getField(name);
if (field != null && field.isFinal() && field.isStatic()) {
return field;
}
}
// look for static or synthetic accessor
if (accessor != null) {
return accessor;
}
if (methodCallArgumentTypes == null) {
// reference may be in method pointer or static import; look for method as last resort
return findMethodDeclaration(name, declaringType, null);
}
return null;
} |
ready to test |
One note: methods still lack the static/non-static checking. Therefore, you may reference an instance method from a closure within a static field/method and get no warning of the impending runtime error. Implicit-this methods (no object expression) are represented as |
Hi Eric, I just updated to 2.9.2.xx-201711060326-e46, but I find a regression here, rather than an improvement. I'm not sure I can follow what you say in your last message... is it a hint about the requirement to open a wider improvement request? Indeed, what I see now is that in (A), |
I retested this with 2.9.2.xx-201711070247-e46 and it seems to be fixed now, thank you! 👍 |
This was (part of) the old GRECLIPSE-1766
Consider the following code:
In (A) and (B) the
foo
field is accessed directly and Greclipse correctly detects this (by colouring it accordingly, by showing this fact when you hover overfoo
and/or press F2 and by providing the correct navigation with F3).In (C) and (D), instead, the
foo
field is accessed through its setter. While in (D) Greclipse correctly determines that (i.e.: it uses a different colour, F2 and F3 work correctly), in (C) Greclipse thinks thatfoo
is accessed directly, but this is not the case, as you can test by running themain
method.This might appear a trivial problem, but it can be very useful for the developer to distinguish between the two cases, especially (as an example) when
foo
is annotated with@Bindable
: in (C) and (D) listeners will be invoked, in (A) and (B) they won't.The text was updated successfully, but these errors were encountered: