I'm beginning to create a new library and I've just spent the last few hours struggling with the (unhelpful) error message: "Cannot parse library definition" when trying to save user-created code.
The cause appears to be incorrect parsing of the content of comments in the library code -- specifically parenthesis within a comment. For example, this causes the error:
That's the real bug, yes — it should be ignoring the entire comment body but isn't. My best guess is still the same mechanism, just applied to comments specifically: a proper parser tokenizes first, which means it recognizes /* ... */ as a single comment token and discards its contents entirely before doing anything else — so nothing inside a comment should ever be visible to a later "find the parens" step. But if Hubitat's library-definition check is a lightweight scan rather than a real tokenizer, it's likely finding the library( block by regex/text-search and then just counting ( and ) characters across the raw file (or across a rough window around that block) to locate the matching close-paren — without first stripping out comments (or, alternatively, it may strip // line comments but have a bug in its /* */ block-comment stripping regex, which is a very common mistake — e.g. a regex that doesn't handle it correctly, or that stops at the first */ incorrectly, or various other edge cases people get wrong when hand-writing comment-stripping regexes).
Either way, the underlying issue is the same: something in their comment-stripping step is failing for /* this (and) that */, which then lets that stray ( leak into whatever paren-matching logic finds the library block. It's exactly the kind of bug that only surfaces when someone happens to put an unbalanced-looking character inside a comment — which is presumably why it went unnoticed until this bug report.
While it won't help, you, an accurate explanation in short is that the library code isn't parsed into Groovy until the library "pre-parser" (a native implementation not using the actual Groovy parser) finds what I thinks is "library()" (or something that could be), so sometimes you're unlucky enough to find something that trips it up before it gets to that point -- and this is one of those. It looks for parentheses to help and is smart enough to remove anything after // characters (again, not real Groovy parsing yet, so if you try to confuse it there by, say, embedding this in a string, you probably could too...), but doesn't try anything for C-style comments, perhaps due to potentially more complexity. This is why your second case doesn't fail.
This leads to three solutions: use // comments, move the C-style comment below library(), or avoid parentheses before library(). The "pre-parser" might be able to be made a bit smarter about this, but I'm not sure if or when that may happen, and it usually works well enough.
While again I know it won't help you in retrospect (sorry! ), the docs have been updated with these recommendations, so hopefully that at least prevents someone from stumbling on it in the future, should they read them.
bertabcd1234 wrote: This leads to three solutions: use // comments, move the C-style comment below library(), or avoid parentheses before library().
Um, you forgot to mention the first, most obvious, and only correct solution... just fix the pre-parser.
Everything you listed is a work-around that users would only do after triggering this bug and after experiencing greater frustration than what I had ("greater", because it's more annoying to be affected by a known bug that isn't fixed).