Omitted using clause causes runtime error in some cases
o The Environment:
Windows 10
Eclipse Neon.3 (4.6.3)
ConnectIQ SDK 2.3.4
o A detailed description of the issue
If you run the below code as-is with the 2.3.4 SDK, you get...
Could not find symbol Graphics.Failed invoking <symbol>Failed loading application
This error message is not very descriptive, but in this case it can be easily reduced to the reference to Graphics.COLOR_PURPLE. If you replace Graphics.COLOR_PURPLE with 0xFF00FF, you get...
Could not find symbol Graphics.Failed invoking <symbol>Could not find symbol TestModule.Failed invoking <symbol>Symbol Not Found Error
in <init> (C:\Users\Travis\Desktop\connectiq_testing\source\TestApp.mc:13)
in onUpdate (C:\Users\Travis\Desktop\connectiq_testing\source\TestApp.mc:54)
That error message is a bit better in that it points to the place where the error occurred. If you replace Graphics.COLOR_BLUE with 0x0000FF, the application runs just fine. If you switch those back and use explicit references (i.e., Toybox.Graphics.COLOR_PURPLE and Toybox.Graphics.COLOR_BLUE, you will note similar problems. If you add the using Toybox.Graphics clause near the top of the file, everything works as expected.
If you put the using clause after the reference to Graphics.COLOR_PURPLE but before the declaration of TestModule, the program behaves properly as well. If you put it inside, or after, TestModule it fails again; but this time the error message indicates there is a problem finding Graphics.COLOR_BLUE from TestModule.
The Developer's Guide does indicate that you are to use the using clause, so it seems that this code is in Undefined Behavior territory, but the fact that it works without this in some contexts can be frustrating. When dealing with a global, there isn't any information about the source of the problem in the error message, which makes it even difficult to fix.
It also seems relevant that it doesn't appear to be necessary to have a using clause for top-level modules defined in other source files. I do, however, see the problem for nested modules.
o Steps to reproduce the issue
Build the below test case. Run it on the simulator.
o Any applicable additional information
N/A
o A code sample that can reproduce the issue (in email only if preferred)
using Toybox.Application as App;
using Toybox.WatchUi as Ui;
using Toybox.Lang;
using Toybox.Timer;
//using Toybox.Graphics;
// this reference requires using clause
var global_color = Graphics.COLOR_PURPLE;
module TestModule
{
// this reference requires using clause
var module_color = Graphics.COLOR_BLUE;
}
class TestView extends Ui.View
{
var counter = 0;
// this reference DOES NOT REQUIRE using clause
var class_color = Graphics.COLOR_GREEN;
function initialize() {
View.initialize();
}
hidden var _M_timer;
function onShow() {
_M_timer = new Timer.Timer();
_M_timer.start(new Lang.Method(Ui, :requestUpdate), 1000, true);
}
function onHide() {
_M_timer.stop();
_M_timer = null;
}
function onUpdate(dc) {
// this reference DOES NOT REQUIRE using clause
var local_color = Graphics.COLOR_RED;
var color;
if (counter == 0) {
color = local_color;
counter = 1;
}
else if (counter == 1) {
color = class_color;
counter = 2;
}
else if (counter == 2) {
color = TestModule.module_color;
counter = 3;
}
else {
color = $.global_color;
counter = 0;
}
dc.setColor(color, color);
dc.clear();
}
}
class TestApp extends App.AppBase
{
function initialize() {
AppBase.initialize();
}
function getInitialView() {
return [ new TestView() ];
}
}