[Flash] Misinterpreted "unresolvable variable"

I just started using IntelliJ at work and noticed a bug.

I have enum-classes that work like this:
public static const TYPE1:SomeType = new SomeType(TYPE1);

That's perfectly valid and FDT thinks it's ok. But IntelliJ doesn't, and gives "unresolvable variable" error at the second "TYPE1".
I've noticed IntelliJ is very smart, but in this case a bit too smart it seems.

Is there perhaps some setting in the error parser that would make this go away?

cheers

10 comments
Comment actions Permalink

We were sure that using a constant before its initialization is forbidden, but somehow ActionScript compiler thinks different. A strange thing happens: although TYPE1 is a constant, it has different values in runtime. First time (when passed to the constructor of SomeType) it is null and after initialization it is an instance of SomeType. What is the purpose of such a strange code? It seems to be equivalent to
public static const TYPE1:SomeType = new SomeType(null);

There's no way to avoid red highlighting in this case in IntelliJ IDEA. You need to open an issue: http://youtrack.jetbrains.net. We'll give the issue higher priority if you explain the sense in such code.

0
Comment actions Permalink

Yeah I understand it may seem strange.

It's a trick used for creating type safe enums.

You can see an example here:
http://www.liranuna.com/typesafe-assignable-enumerations-in-as3/


To make it completely safe the constructor needs to look something like this:


public function SomeType (enum:SomeType)
 {
     if (enum && enum != this)
     {
          throw new Error(........

This prevents from passing 'null' as an argument.

0
Comment actions Permalink

I'm afraid I still do not understand the difference in the following 2 lines:

public static const TYPE1:SomeType = new SomeType(TYPE1);
public static const TYPE1:SomeType = new SomeType(null);


And I don't see any sence in enum != this check in constructor as it is always true.

Am I wrong?

0
Comment actions Permalink

The check is there to prevent someone from doing just new SomeType(null) or new SomeType(SomeType.TYPE1).

In the constructor it can actually match the 'enum' argument with itself.

0
Comment actions Permalink
The check is there to prevent someone from doing just new SomeType(null) or new SomeType(SomeType.TYPE1)

It doesn't prevent from doing new SomeType(null) because following conditions are equivalent:

if (enum && enum != this)
if (enum != null && enum != this)

In the constructor it can actually match the 'enum' argument with itself.

If you stop at a breakpoint inside constructor you'll see that when the constant is initialized null is passed to the costructor, although in the code we see that the costant itself is passed. That's why I conclude that following are absolutely equivalent:

public static const TYPE1:SomeType = new SomeType(TYPE1);
public static const TYPE1:SomeType = new SomeType(null);
0
Comment actions Permalink

Oh, sorry. This is how it should look:

if (!enum || enum != this)

Regarding the instantiation I can only say that as far as I know it works. But if you test it (I'm not in a position to do so myself) and you're able to do new SomeType(SomeType.TYPE1), well then you've proven me wrong! :)

0
Comment actions Permalink

Ok, as following lines are equivalent:
if (!enum || enum != this) {throw new Error()}
if (enum == null || enum != this) {throw new Error()}

you always get error thrown when the constant is initalized

public static const TYPE1:SomeType = new SomeType(TYPE1);

because
TYPE1==null at the moment when it is passed to the constructor.
That's why I still see no sense in this code.
0
Comment actions Permalink

I just had the chance to test this myself, and your right.

I've been using this class for so long that I've just assumed it was working, or rather, I have forgotten how it really is supposed to work.

I realize now that if (enum && enum != this) was correct. Though it only protects from new SomeType(SomeType[any type]) but NOT from new SomeType(null).

And, as you've pointed out, the 'enum' argument is indeed always 'null', and you could say I might as well skip passing any argument.

However, since the argument is there, you could argue it is more safe since a developer would go "ok I write new SomeType(..   oh there's an argument.. let's put one in...    oh I can't.. I get an error saying I shouldn't instanciate this class".
With no argument, writing new SomeType() would be the equivalent of writing new SomeType(null) and accidently writing new SomeType() will likely happen more often.

Well, well. I will probably stop using this method now having realized this, since I've found other perfectly safe versions of AS3 enums.



So, thanks a lot for your input and quick response, and sorry for taking your time! At least I learned something. :)


I do believe though, since the compiler is fine with passing itself, that my example should produce a warning and not an error.

0
Comment actions Permalink

Yes, warning would be better. Please open an issue: http://youtrack.jetbrains.net
Just curious, what other perfectly safe versions of AS3 enums do you use now?

0

Please sign in to leave a comment.