#requires-modules psworkflow
#requiresCrazyThings -psed desktop
The #Requires directive doesn't seem to require some kind of separation from its keyword to the next token, but not providing that separation causes an error anyway.
PS C:\> #requiresCrazyThings -psed desktop
At line:1 char:2
+ #requiresCrazyThings -psed desktop
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cannot process the #requires statement because it is not in the correct format.
The #requires statement must be in one of the following formats:
"#requires -shellid <shellID>"
"#requires -version <major.minor>"
"#requires -psedition <edition>"
"#requires -pssnapin <psSnapInName> [-version <major.minor>]"
"#requires -modules <ModuleSpecification>"
"#requires -runasadministrator"
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptRequiresInvalidFormat
PS C:\>
I am just not sure this is right. A inexperienced user could stumble across this by accident thinking he's just entering a comment. I have seen plenty of reports already of new users who are confused when the editor starts highlighting items in a comment, turning them in as bug reports.
Isn't the error message helpful ?
More fundamentally, the issue is that it is problematic that the syntactic form of a _comment_ was chosen to implement "preprocessor directives" (statements evaluated at script/module parse time), which invites confusion.
I suggest either reframing this issue accordingly or creating a new issue to suggest a distinct syntax form.
I just think that #requires should be held to the same standard as any other keyword, it must adhere to delimiter standards to be acknowledged. #requiresCrazyThings does not meet the delimiter requires anywhere else in PowerShell for a keyword of #requires. Everywhere else, the token would be #requiresCrazyThings and that is not the same as #requires. Because it doesn't match the required special preprocessor directive keyword, the line should be ignored, not produce an error for an 'almost' attempt.
I do realize that this is a case of error one way or the other, but I think because its based on a comment marker, the error should be in the direction of ignoring anything that isn't exactly right. Its a comment, and instead let the user figure out why his very badly malformed #requires directive isn't working. If the keyword token has met the standard delimiter and the rest of the syntax is in error, then display an error.
Background, I am working on a PR over at PowerShell/EditorSyntax, https://github.com/PowerShell/EditorSyntax/pull/156, and trying to make sure it mostly matches what PowerShell really expects.
I do realize that this is a case of error one way or the other, but I think because its based on a comment marker, the error should be in the direction of ignoring anything that isn't exactly right.
On purely _technical_ grounds I'd agree: if something isn't a syntactically valid #requires directive, it shouldn't be treated as one.
However, falling back to the _other_ construct that shares the #-prefixed syntax - a comment - means that what the user _may_ have intended to be a #requires directive will be _quietly ignored_.
My sense is that this quiet ignoring would be worse than the current behavior, as a script author may not notice that a directive they meant to put in place wasn't.
If they _didn't_ mean to create a #requires directive and #requiresCrazyThings was actually meant to be a comment, then at least the error message will alert them to how their comment is being interpreted as _something else_ - and working around the problem - should it ever arise - is trivial: simply put a space between # and requires.
As simple as that workaround is - and if we stick with the current behavior the error message should be amended to suggest it - it highlights the fundamental problem:
Comment syntax should never have been overloaded to serve as directive syntax too, and a proper solution requires a distinct syntax form for directives.
In general I tend to lean towards always having a leading space on my comments following the # symbol, so I guess I've never run into this as an issue. I agree, though, that using the standard comment syntax as a directive is probably not the best.
I'm sure it was intended to reflect back on C#'s preprocessor-directive syntax, but that might have been a bad idea.
Not sure if it can really be changed now, though? I guess it wouldn't be the end of the world, as changing it would essentially mean that all current #Requires statements are just... comments. I guess it'd be OK?
Not sure what we could really use instead. Any thoughts on viable alternatives @mklement0? 馃
The using directives already are bona fide statements (though, unlike the #requires directives, they must be at the top of the script).
using module even more or less does the same thing as #requires -module (the former additionally loads PS classes).
using isn't really the right name for the other #requires directives (using runasadministrator?), however, so perhaps a separate requires keyword is called for.
I'm pretty sure that an RFC is needed to propose something of that magnitude.
In the current situation, my recommendation is to merely amend the error message so that if someone writes #requiresCrazyThings or even #requires time to process (where #requires is technically a valid keyword), they'll see something along the lines of "If you meant to write a comment instead, put a space between '#' and the word 'requires'" after the current message.
A couple thoughts:
requires does, except that if the requires directive is skipped, eventually an error will occur. Its just that by then, the damage might already have been done. A properly written program would have damage control. In this case, requires could be just a easy way out of writing damage control.#requires-modules psworkflow still returns an error, while anywhere else in PowerShell, the token would been decoded as requires-modules and that wouldn't match requires. I unfortunately do not have enough experience with other languages that do this (commented directives) to know how they behave, but the behavior seems odd.usings requirement to be the first line(s) is solution to the reservation of a keyword, albeit with its own restrictions. using namespace could just as well as been a comment directive, as its not critical (it just makes the writer type longer name spaces).In actuality, most of the work of using or #requires can be accomplished directly in the scripting language, where more specific error messages could be crafted, or even the issue worked around, maybe with the exception of importing classes from a module.
I can implement the current syntax in the tmlanguage grammar, it will just be the odd one out, in all the rules, and is why I bring this up. I think its better to have a good understanding of the grammar than to just assume it works a certain way, hence my investigation in to it in the first place.
Most helpful comment
In general I tend to lean towards always having a leading space on my comments following the
#symbol, so I guess I've never run into this as an issue. I agree, though, that using the standard comment syntax as a directive is probably not the best.I'm sure it was intended to reflect back on C#'s preprocessor-directive syntax, but that might have been a bad idea.
Not sure if it can really be changed now, though? I guess it wouldn't be the end of the world, as changing it would essentially mean that all current
#Requiresstatements are just... comments. I guess it'd be OK?Not sure what we could really use instead. Any thoughts on viable alternatives @mklement0? 馃