Big update to prettier-extension-monkeyc

I've posted about prettier-extension-monkeyc before, but I've added a bunch of new features that developers will probably like (well, I've been missing them, so maybe you have too).

The new features it implements for VSCode include:

  • Goto Definition. Point at a symbol, Ctrl/Cmd click, and it will take you to the definition. Or F12
  • Goto References. Right click on a symbol and select "Goto References". It will show you all the references. Or Shift-F12
  • Peek Definition/Peek References. Same as above, but in a popup window so you don't lose your place in the original document.
  • Rename Symbol. Right click on a local, function, class or module name, and select "Rename Symbol". It will rename all the references. It doesn't yet work for class members/methods.
  • Goto Symbol. Type Ctrl/Cmd-Shift-O and pick a symbol from the drop down (which has a hierarchical view of all symbols in the current file). This also appears as an outline across the top of the file.
  • Open Symbol By Name. Type Ctrl/Cmd-T, then start typing letters from a symbol name. A drop down will be populated with all matching symbols from anywhere in your project.

Older features include a prettier based formatter for monkeyc, and a monkeyc optimizer that will build/run/export an optimized version of your project.

[edit: My last couple of replies seem to have just disappeared, and the whole conversation seems to be in a jumbled order, so tldr: there's a new test-release at https://github.com/markw65/prettier-extension-monkeyc/releases/tag/v2.0.9 which seems to work for me on linux. I'll do more verification tomorrow, and push a proper update to the vscode store once I'm sure everything is working]

  • const Z = -1.0;

    This is just another instance of the const initializer issue. I was only processing literals, and literals with casts, and -1.0 is actually a unary "-" applied to the constant 1.0. As soon as the optimizer starts to run, it converts it to the literal -1.0, but it looks like you got this error from the analysis phase - which doesn't actually do any optimization.

    mA = vJ; // Invalid assignment to mA. Expected Number but got Number or Enum[pmc-analysis]
    mA = hJ | vJ; // Invalid assignment to mA. Expected Number but got Boolean[pmc-analysis]

    This is the same as the "backgroundColor in setColor" issue, which I've just found the fix for.

  • v2.0.43 is out.

    Fixes all of the issues reported by with possible exception of the mysterious "remove" errors. It does fix two separate bugs that were each capable of causing similar errors.

  • The simple warnings I reported yesterday are gone.

    The add/remove is still there Disappointed I tried to make a minimal version that still reproduces it:

    import Toybox.Lang;
    
    class Test {
        class Foo {
            public function add(rrIntervalDiff as Number?) as Void {}
            public function remove(numberOfItems as Number) as Void {}
        }
        var cond as Boolean = true;
        var calc as Foo = new Foo();
        var rr as Number?;
        public function t() as Void {
            test();
        }
        (:hrv, :inline)
        hidden function test() as Void {
            var calc = self.calc;
            var b = 3;
            var rr = self.rr;
            if (!cond) {
                var lrr = rr;
                rr = 4;
                var rrD = null;
                if (lrr != null && rr != null) {
                    rrD = rr - lrr;
                    calc.add(rrD);
                }
            } else {
                calc.remove(b);
            }
        }
    }
    

    Let me know if this works for you (it only reproduces it when I call T.test(), so you might need more code "before" that to reproduce but I believe this should work as T.test is in another class, doesn't get any argument and is not inlined) 

    When at the declaration of a constant then depending on the type it either shown me the places the constant is used, or the definition itself.

    const A = 2; // works, shows every place it's used

    const B = [] as Array<Number>; // shows the declaration, not the usage

  • Let me know if this works for you

    Yes! Finally :-)

  • (:foo)
    function a() {
        b(1); // $.C.b expects 1 arguments, but got 1[pmc-analysis]
        b(2); // $.C.b expects 1 arguments, but got 1[pmc-analysis]
    }
    (:bar)
    function a() {
        b(1, 10); // $.C.b expects 1 arguments, but got 2[pmc-analysis]
        b(2, 20); // $.C.b expects 1 arguments, but got 2[pmc-analysis]
    }
    
    (:foo)
    function b(x as Number) as Void {
    }
    (:bar)
    function b(x as Number, y as Number) as Void {
    }

  • The add/remove is still there

    Should be fixed in v2.0.44.

    There was an inlining bug that could cause locals from the callee to seem to belong to the callee's outer scope (ie Test in this case). So the type checker saw two definitions for calc - the one from Test, and the one from Test.test. The one from Test.test has no type declaration (since it's a local), so the inferred type was Any.

    Note that again, this never causes incorrect optimizations, because the inferred type will always be at least as generic as the correct one (and in this case, much more generic). So there might be missed opportunities (although I doubt it in this case), but shouldn't be incorrect code.

  • $.C.b expects 1 arguments, but got 1[pmc-analysis]

    This is as intended I'm afraid. In analysis mode, it throws in all the possible source files, and ignores all the exclude annotations, and then reports on the result.

    There doesn't seem to be any point in doing this in real life; why not give the two b's different names, since they're clearly different functions...

    But I should probably add an option to turn the analysis off if you really have cases like this...

  • When at the declaration of a constant then depending on the type it either shown me the places the constant is used, or the definition itself

    Sorry, not quite clear on what you mean? Are you talking about cmd-clicking on A or B? That seems to try to do some kind of smart visit-refs or visit-defs depending on what you click on:

    • If you click on a reference, and there's a single definition, it takes you to the definition; if there are multiple definitions it opens a "peek" window with all the definitions
    • If you click on a definition and there's a single definition, and a single reference, it takes you to the reference; if there are multiple references it opens a peek window.
    • If you click on a definition and there are multiple definitions, it opens a peek window on the definitions.

    All of this is handled by VSCode - all I do is provide the locations of the definitions and references.

    You can also explicitly invoke "Goto References" or "Goto Definitions" from the context menu, or a key binding.

    If you mean something else, or you're seeing some other behavior, can you be more specific?

  • so in 2.0.44 all the other warnings are gone, but one is left from this, where it has the return r at the end of foo():

    Expected $.C.foo to return Number or String but got Null or Number or String

    Let me know if you want to deal with this (and if the above is enough to reproduce it). For now I'll add "return r as Number or String" :)

  • This is exactly what I meant. Now I understand that this is the strange behaviour of VSC. The last case doesn't make much sense to me: when I click on a definition then I'd like to see the ref or the peek window of the refs.

    There IS some thing that you might be able to improve here: since you provide VSC with the lists you can take the annotations into account. But this still won't fix the 3rd thing I guess. Why doesn't VSC display a peek window with all the references???