koalaman / shellcheck

ShellCheck, a static analysis tool for shell scripts
https://www.shellcheck.net
GNU General Public License v3.0
36.55k stars 1.78k forks source link

function definition should allow compound command #2130

Open mmjo opened 3 years ago

mmjo commented 3 years ago

For bugs

For new checks and feature suggestions

Here's a snippet or screenshot that shows the problem:

#!/bin/bash
f() [[ 1 = 1 ]]

Here's what shellcheck currently says:

Line 2  SC1073: Couldn't parse this function. Fix to allow more checks.
Line 2  SC1064: Expected a { to open the function definition.
Line 2  SC1072:  Fix any mentioned problems and try again.

Here's what I wanted or expected to see:

No warnings.

Musings

It seems from src/Parser.hs in readFunctionDefinition that shellcheck only allows f() {...} and f() (...).

Though both bash and posix allow a compound command as function body.

Note that the readCompoundCommand could have been useful. But unfortunately it includes readFunctionDefinition itself.

matthewpersico commented 3 years ago

What would this do? If you try something useful:

 $ f() echo hello
-bash: syntax error near unexpected token `echo'
mmjo commented 3 years ago

'echo hello' is not a compound command, so the error is expected.

A slightly more useful example: is_ok () [[ "$1" = 42 ]]

Compare against the verbose version (no need for a return, but do not forget the semicolon): is_ok () { [[ "$1" = 42 ]]; }

You can even write: is_ok () if [ "$1" = 42 ]; then return 0; else return 1; fi

Instead of an 'if'-statement, a case/while/until/select/for statement is also possible. [but these i never use]

Last possibility is arithmetic. E.g. is_ok () (( "$1" - 42 == 0 ))

matthewpersico commented 3 years ago

TIL

TinCanTech commented 3 years ago

Last possibility is arithmetic. E.g. is_ok () (( "$1" - 42 == 0 ))

According to Douglas Adams, The Answer is not 42 because The Question is:

42 was a Deep-Thought error. Which was the reason for Earth.

oguz-ismail commented 3 years ago
 $ f() echo hello
-bash: syntax error near unexpected token `echo'

@matthewpersico most shells (including the ones below and also /bin/sh on FreeBSD, NetBSD, Solaris 10, and UnixWare 7.1.4) accept a pipeline as function body, bash and yash are the exceptions.

$ for sh in bash bosh 'busybox sh' dash gwsh mksh ksh oksh yash zsh; do echo $sh; $sh -c 'f() echo a; f'; done
bash
bash: -c: line 1: syntax error near unexpected token `echo'
bash: -c: line 1: `f() echo a; f'
bosh
a
busybox sh
a
dash
a
gwsh
a
mksh
a
ksh
a
oksh
a
yash
yash -c:1: syntax error: a function body must be a compound command
zsh
a
koalaman commented 3 years ago

Note that the readCompoundCommand could have been useful. But unfortunately it includes readFunctionDefinition itself.

This is not a problem for dash:

$ f() f() { echo foo; }
$ f
$ f
foo

The original reason for not allowing anything other than {} and () was that ShellCheck kept giving misleading advice when it interpreted bad array assignments and similar as possible function definitions. However, a lot of that parsing was rewritten in 0.7.2, so it may be feasible to allow this again.