BashSupport-Pro / bashsupport-pro

Public issue tracking for BashSupport Pro. This is a plugin, which provides advanced support for Bash scripts for JetBrains IDEs.
https://www.bashsupport.com
48 stars 2 forks source link

Spaces in array keys break parser #142

Open Bilge opened 1 year ago

Bilge commented 1 year ago
local -A foo=([bar baz]=bat)
echo "${foo[bar baz]}"
jansorg commented 1 year ago

It's complicated with Bash... man bash says:

Indexed arrays are referenced using integers (including arithmetic expressions) and are zero-based; associative arrays are referenced using arbitrary strings. Unless otherwise noted, indexed array indices must be non-negative integers.

That means that the type of the key and how it's interpreted is runtime behavior. Keys are currently parsed as arithmetic expressions, i.e. the parser assumes an indexed array. Unfortunately it's not possible to track the type of array in the parser.

For the current version of BashSupport Pro (3.x), I recommend the workaround to use a string key:

local -A foo=(["bar baz"]=bat)
echo "${foo["bar baz"]}"

I'll try to find a better way to handle this for the next major version. I could be possible to not show an error for array keys, but that might be too much if it's actually an indexed array :( Please let me know what you'd expect as a developer here. Thanks!

Here's an example:

a=1
b=2
declare -a plainArray=()
declare -A assocArray=()
plainArray[a + b]="value"
assocArray[a + b]="value"
declare -p plainArray assocArray

prints this:

declare -a plainArray=([3]="value")
declare -A assocArray=(["a + b"]="value" )
Bilge commented 1 year ago

Unfortunately it's not possible to track the type of array in the parser.

Why is that the case? Although (indexed) arrays can be declared implicitly with foo=(), one cannot possibly create an associative array without either delcare -A or local -A, and arrays cannot be passed around, so it has to be explicitly declared in the current scope.

jansorg commented 1 year ago

There‘s a separation of lexing/parsing (i.e. the text-based syntax analysis) and the semantic analysis (e.g. „unused variable“, tracking of variable flags), which happens based on the parsed syntax tree.

Even with the semantic analysis, flag „associative array“ can‘t be reliably tracked, e.g. for declarations which are nested in conditional commands or access to global array variables in functions, which could be called from any context.

static analysis of syntax, which relies on runtime information, isn‘t possible in a reliable way. I hope to find good enough solution to accept most values with whitespace.

most likely shfmt and ShellCheck have their own workarounds for this, I‘ll investigate what they‘re doing…

jansorg commented 1 year ago

There‘s already tracking of flags, it‘s shown by quick documentation on a variable. But it doesn‘t work yet with conditional commands, etc.