Bug #9354
Invalid handle (3135) error is thrown insted of the 10068 error.
90%
Related issues
History
#2 Updated by Artur Școlnic over 1 year ago
start.p
new MyClass():my_class:mtd().
MyClass.cls
class MyClass:
define public variable my_class as class MyClass.
method void mtd():
message "executing...".
end method.
end class.
The error
Invalid handle. Not initialized or points to a deleted object. (3135) is thrown in FWD, the correct error message is:Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a user-defined type and valid (not UNKNOWN). (10068)#3 Updated by Artur Școlnic over 1 year ago
This issue is derived from #9271-11.
#4 Updated by Alexandru Lungu over 1 year ago
- Assignee set to Eduard Marcu
#5 Updated by Eduard Marcu over 1 year ago
- Status changed from New to WIP
#6 Updated by Eduard Marcu over 1 year ago
- % Done changed from 0 to 20
I can reproduce the issue. The problem is in object.ref:
public T ref() { if (isUnknown()) { String msg = "Invalid handle. Not initialized or points to a deleted object"; ErrorManager.recordOrThrowError(3135, msg, false); // TODO: is there any scenario where we can actually return null in silent error mode? // (If so, that is very bad.) return null; } return ref; }
We need to make a distinction between chained and unchained objects so that both of these snippets throw the correct error:
new MyClass():my_class:mtd().
10068
define var obj as MyClass no-undo. obj:mtd().
3135
#7 Updated by Eduard Marcu over 1 year ago
- % Done changed from 20 to 50
class MyClass:
define public variable my_class as class MyOtherClass.
method void mtd1():
message "executing...".
end method.
end class.
class MyOtherClass:
method void mtd():
message "executing...".
end method.
end class.
Let's look at the following OE cases:
I:
new MyClass():my_class:mtd().
FWD & OE Output:
Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a user-defined type and valid (not UNKNOWN). (10068)
II:
define var obj as MyClass no-undo. obj:mtd1().
FWD & OE Output: Invalid handle. Not initialized or points to a deleted object. (3135)
III:
def var x as MyClass no-undo. x:my_class:mtd().
FWD & OE Output: Invalid handle. Not initialized or points to a deleted object. (3135) then another window with Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a user-defined type and valid (not UNKNOWN). (10068)
My changes:
=== modified file 'rules/convert/oo_calls.rules' --- old/rules/convert/oo_calls.rules 2023-10-31 13:04:48 +0000 +++ new/rules/convert/oo_calls.rules 2024-12-12 13:10:29 +0000 @@ -419,8 +419,23 @@ lastid) </action> </rule> - - <action>lastid = createJavaAst(java.method_call, "ref", lastid)</action> + + + + <rule>copy.type == prog.object_invocation and downPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "chainedRef", lastid) + </action> + <rule on="false">copy.type == prog.object_invocation and upPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "firstChainedRef", lastid) + </action> + <action on="false"> + lastid = createJavaAst(java.method_call, "ref", lastid) + </action> + </rule> + </rule> + <action>ref1.putAnnotation("peerid", lastid)</action> <!-- unqualified method invocations as the first referent, this can only happen for === modified file 'src/com/goldencode/p2j/util/object.java' --- old/src/com/goldencode/p2j/util/object.java 2024-03-24 09:17:59 +0000 +++ new/src/com/goldencode/p2j/util/object.java 2024-12-12 13:32:36 +0000 @@ -265,6 +265,39 @@ return ref; } + + public T chainedRef() + { + if (isUnknown()) + { + String msg = "Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a user-defined type and valid (not UNKNOWN)"; + ErrorManager.recordOrThrowError(10068, msg, false); + + // TODO: is there any scenario where we can actually return null in silent error mode? + // (If so, that is very bad.) + return null; + } + + return ref; + } + + public T firstChainedRef() + { + if (isUnknown()) + { + String msg1 = "Invalid handle. Not initialized or points to a deleted object"; + + String msg2 = "Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a " + + "user-defined type and valid (not UNKNOWN)"; + + ErrorManager.recordOrThrowError(new int[] { 3135, 10068 }, new String[] { msg1, msg2 }, false); + // TODO: is there any scenario where we can actually return null in silent error mode? + // (If so, that is very bad.) + return null; + } + + return ref; + } /** * Compares this instance with the specified instance and returns -1 if this instance is less than the
Should I:
A) Make a single ref method with a flag parameter that takes care of all the cases? (i.e normal ref, chainedRef, firstChainedRef)
B) Have two refs: the original ref and chainedRef with a flag parameter that takes care of chainedRef & firstChainedRef
#8 Updated by Alexandru Lungu over 1 year ago
I think your approach is right. Please consider:
define var obj as MyClass no-undo. obj = new MyClass(). obj:gen():gen():test():test(). message "finish".
class MyClass:
method MyClass gen():
return new MyClass().
end.
method MyClass test():
return ?.
end.
end.
Note how there is a way larger chain. But this results only in the Lead attributes in a chained-attribute expression exception. Please do some extra investigation with such construct to ensure your path is right - from my POV it is.
Should I:
A) Make a single ref method with a flag parameter that takes care of all the cases? (i.e normal ref, chainedRef, firstChainedRef)
B) Have two refs: the original ref and chainedRef with a flag parameter that takes care of chainedRef & firstChainedRef
I like the second version more. Maybe use ref(), chainedRef() (which will call chainedRef(false) underneath) and chainedRef(true) (which means the first ref in the chain). The overloading will help generating less code, defaulting the no-flag to false-flag.
Greg, any other suggestion?
#9 Updated by Greg Shah over 1 year ago
I like the second version more. Maybe use
ref(),chainedRef()(which will callchainedRef(false)underneath) andchainedRef(true)(which means the first ref in the chain). The overloading will help generating less code, defaulting the no-flag to false-flag.
I think this is probably the best approach. I like it better than the firstChainedRef() method.
#10 Updated by Eduard Marcu over 1 year ago
For the progress code given by Alex: obj:gen():gen():test():test().
[java] Caused by: java.lang.NullPointerException: Cannot invoke "com.goldencode.ast.Aast.getId()" because the return value of "com.goldencode.ast.Aast.getChildAt(int)" is null
[java] at com.goldencode.expr.CE16173.execute(Unknown Source)
[java] at com.goldencode.expr.Expression.execute(Expression.java:398)
=== modified file 'rules/convert/oo_calls.rules' --- old/rules/convert/oo_calls.rules 2023-10-31 13:04:48 +0000 +++ new/rules/convert/oo_calls.rules 2024-12-13 14:33:07 +0000 @@ -419,8 +419,26 @@ lastid) </action> </rule> - - <action>lastid = createJavaAst(java.method_call, "ref", lastid)</action> + + + + <rule>copy.type == prog.object_invocation and downPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "chainedRef", lastid) + </action> + <rule on="false">copy.type == prog.object_invocation and upPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "chainedRef", lastid) + </action> + <action on="true"> + createJavaAst(java.bool_true, "", getAst(lastid).getChildAt(0).getId()) + </action> + <action on="false"> + lastid = createJavaAst(java.method_call, "ref", lastid) + </action> + </rule> + </rule> + <action>ref1.putAnnotation("peerid", lastid)</action> <!-- unqualified method invocations as the first referent, this can only happen for === modified file 'src/com/goldencode/p2j/util/object.java' --- old/src/com/goldencode/p2j/util/object.java 2024-03-24 09:17:59 +0000 +++ new/src/com/goldencode/p2j/util/object.java 2024-12-13 08:07:59 +0000 @@ -265,6 +265,33 @@ return ref; } + + public T chainedRef() + { + return chainedRef(false); + } + + public T chainedRef(boolean isFirst) + { + if(isUnknown()) + { + String msg1 = "Invalid handle. Not initialized or points to a deleted object"; + String msg2 = "Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a " + + "user-defined type and valid (not UNKNOWN)"; + if(isFirst) + { + ErrorManager.recordOrThrowError(new int[] { 3135, 10068 }, new String[] { msg1, msg2 }, false); + } + else + { + ErrorManager.recordOrThrowError(10068, msg2, false); + } + return null; + } + + return ref; + } + /** * Compares this instance with the specified instance and returns -1 if this instance is less than the
If we remove java.bool_true action the jast tree would look like this:
<ast col="0" id="240518168642" line="0" text="chainedRef" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:426"/>
<ast col="0" id="240518168643" line="0" text="test" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:381"/>
<ast col="0" id="240518168644" line="0" text="chainedRef" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:426"/>
<ast col="0" id="240518168645" line="0" text="gen" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:381"/>
<ast col="0" id="240518168646" line="0" text="chainedRef" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:426"/>
<ast col="0" id="240518168647" line="0" text="gen" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:381"/>
<ast col="0" id="240518168648" line="0" text="chainedRef" type="METHOD_CALL">
<annotation datatype="java.lang.String" key="byrule" value="convert/oo_calls.rules:430"/>
<ast col="0" id="240518168649" line="0" text="obj" type="REFERENCE">
<annotation datatype="java.lang.Long" key="peerid" value="94489280559"/>
<annotation datatype="java.lang.String" key="peerid-byrule" value="convert/variable_references.rules:1018"/>
<annotation datatype="java.lang.String" key="byrule" value="convert/variable_references.rules:1018"/>
It seems that <ast col="0" id="240518168649" line="0" text="obj" type="REFERENCE"> is added after my attempt at setting chainedRef to true.
I think what is needed is to put an annotation when chainedRef should be true and after a REFERENCE gets added to jast, we verify the existence of that annotation and add java.bool_true node to jast.
#11 Updated by Greg Shah over 1 year ago
I think what is needed is to put an annotation when
chainedRefshould be true and after aREFERENCEgets added to jast, we verify the existence of that annotation and addjava.bool_truenode to jast.
Correct. You must defer the creation of the boolean node until after the reference obj is created.
#12 Updated by Eduard Marcu over 1 year ago
- % Done changed from 50 to 70
There are some prints for debugging reasons.
=== modified file 'rules/convert/oo_calls.rules' --- old/rules/convert/oo_calls.rules 2023-10-31 13:04:48 +0000 +++ new/rules/convert/oo_calls.rules 2024-12-16 14:02:55 +0000 @@ -419,8 +419,31 @@ lastid) </action> </rule> - - <action>lastid = createJavaAst(java.method_call, "ref", lastid)</action> + + + + <rule>copy.type == prog.object_invocation and downPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "chainedRef", lastid) + </action> + <rule on="false">copy.type == prog.object_invocation and upPath(copy, prog.object_invocation) + <action on="true"> + lastid = createJavaAst(java.method_call, "chainedRef", lastid) + </action> + <action on="true"> + copy.putAnnotation("first-chained-ref", #(java.lang.Boolean) true) + </action> + <action on="true"> + print("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY") + </action> + <action on="false"> + lastid = createJavaAst(java.method_call, "ref", lastid) + </action> + </rule> + </rule> + + + <action>ref1.putAnnotation("peerid", lastid)</action> <!-- unqualified method invocations as the first referent, this can only happen for === modified file 'rules/convert/variable_references.rules' --- old/rules/convert/variable_references.rules 2024-07-30 07:32:38 +0000 +++ new/rules/convert/variable_references.rules 2024-12-16 14:28:02 +0000 @@ -667,7 +667,7 @@ </rule> </rule> </rule> - + <!-- convert variable references, bypass widget references and handles referenced into TABLE-HANDLE FOR --> <rule>evalLib("variables") and @@ -1016,7 +1016,21 @@ <!-- emit variable/accessor --> <action>createPeerAst(methodType, methodTxt, lastid)</action> - + + <rule>parent.type == prog.var_class + <action> + print("######") + </action> + </rule> + <rule>copy.parent.type == prog.object_invocation and + #(java.lang.Boolean) copy.parent.getAnnotation("first-chained-ref") + <action> + printf("%d", this.type) + </action> + <action> + lastid = createJavaAst(java.bool_true, "", lastid) + </action> + </rule> <rule>numImmediateChildren == 0 and copy.isAnnotation("wrapNodeId") <!-- simple vars: emit the 'io' = true parameter here --> <action>lastid = copy.getAnnotation("wrapNodeId")</action> === modified file 'src/com/goldencode/p2j/util/object.java' --- old/src/com/goldencode/p2j/util/object.java 2024-03-24 09:17:59 +0000 +++ new/src/com/goldencode/p2j/util/object.java 2024-12-13 08:07:59 +0000 @@ -265,6 +265,33 @@ return ref; } + + public T chainedRef() + { + return chainedRef(false); + } + + public T chainedRef(boolean isFirst) + { + if(isUnknown()) + { + String msg1 = "Invalid handle. Not initialized or points to a deleted object"; + String msg2 = "Lead attributes in a chained-attribute expression (a:b:c) must be type HANDLE or a " + + "user-defined type and valid (not UNKNOWN)"; + if(isFirst) + { + ErrorManager.recordOrThrowError(new int[] { 3135, 10068 }, new String[] { msg1, msg2 }, false); + } + else + { + ErrorManager.recordOrThrowError(10068, msg2, false); + } + return null; + } + + return ref; + } + /** * Compares this instance with the specified instance and returns -1 if this instance is less than the
This works fine on #9354-8 and #9354-7 II and III but on I it fails because it doesn't manage to set the first chainedRef to true. I need to find a better place for lastid = createJavaAst(java.bool_true, "", lastid) to take place.
#13 Updated by Eduard Soltan 5 months ago
- Related to Feature #9545: confirm/add table parameter support added
#14 Updated by Eduard Soltan 5 months ago
- Assignee changed from Eduard Marcu to Eduard Soltan
I will take this over as there some tests in tests/table/parameter which have the same root cause as this one.
#15 Updated by Eduard Soltan 5 months ago
- % Done changed from 70 to 90
Committed on 9354a, rev. 16442, patch from #9354-12 + some additional fixes. I have tested CHUI conversion and build (will convert large GUI application today).