feat: implement complete tree-sitter-shellspec grammar with comprehensive testing

- Add full ShellSpec grammar extending tree-sitter-bash
- Support all ShellSpec constructs: Describe, Context, It, hooks, utilities
- Include Data block parsing with statements and argument styles
- Add 61 comprehensive test cases covering real-world patterns
- Implement optimized GitHub workflows with CI/CD automation
- Configure complete development tooling (linting, formatting, pre-commit)
- Add comprehensive documentation and contribution guidelines
- Optimize grammar conflicts to zero warnings
- Support editor integration for Neovim, VS Code, Emacs

Breaking Changes:
- Initial release, no previous API to break

BREAKING CHANGE: Initial implementation of tree-sitter-shellspec grammar

# Conflicts:
#	.github/workflows/codeql.yml
#	.github/workflows/pr-lint.yml
#	.pre-commit-config.yaml

# Conflicts:
#	.github/workflows/pr-lint.yml

# Conflicts:
#	.github/workflows/pr-lint.yml
This commit is contained in:
2025-09-12 18:18:08 +03:00
parent 12d20a17b4
commit c8ba576b4e
77 changed files with 433271 additions and 242 deletions

View File

@@ -0,0 +1,131 @@
================================================================================
Basic Context block
================================================================================
Context "when condition is true"
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
ExampleGroup block
================================================================================
ExampleGroup "group of examples"
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Focused Context block
================================================================================
fContext "focused context"
echo "focused"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Skipped Context block
================================================================================
xContext "skipped context"
echo "skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Context with raw string
================================================================================
Context 'raw string context'
local var="test"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (raw_string)
(declaration_command
(variable_assignment
name: (variable_name)
value: (string
(string_content))))))
================================================================================
Context with word description
================================================================================
Context simple_context
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (word)
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Empty Context block
================================================================================
Context "empty context"
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))))

View File

@@ -0,0 +1,143 @@
================================================================================
Basic Describe block
================================================================================
Describe "basic functionality"
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Focused Describe block
================================================================================
fDescribe "focused test"
echo "focused"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Skipped Describe block
================================================================================
xDescribe "skipped test"
echo "skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Describe with raw string
================================================================================
Describe 'raw string test'
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (raw_string)
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Describe with word description
================================================================================
Describe simple_test
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (word)
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Empty Describe block
================================================================================
Describe "empty test"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))))
================================================================================
Describe with multiple statements
================================================================================
Describe "multiple statements"
echo "first"
echo "second"
local var="value"
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))
(command
name: (command_name
(word))
argument: (string
(string_content)))
(declaration_command
(variable_assignment
name: (variable_name)
value: (string
(string_content))))))

219
test/corpus/hook_blocks.txt Normal file
View File

@@ -0,0 +1,219 @@
================================================================================
BeforeEach hook
================================================================================
BeforeEach
setup_environment
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
BeforeEach with label
================================================================================
BeforeEach "setup database"
init_database
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(word)))))
================================================================================
AfterEach hook
================================================================================
AfterEach
cleanup_environment
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
AfterEach with label
================================================================================
AfterEach "cleanup database"
cleanup_database
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(word)))))
================================================================================
BeforeAll hook
================================================================================
BeforeAll
global_setup
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
BeforeAll with raw string label
================================================================================
BeforeAll 'global setup'
global_setup
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(raw_string)))
(command
name: (command_name
(word)))))
================================================================================
AfterAll hook
================================================================================
AfterAll
global_cleanup
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
BeforeCall hook
================================================================================
BeforeCall
prepare_call
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
AfterCall hook
================================================================================
AfterCall
verify_call
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
BeforeRun hook
================================================================================
BeforeRun
prepare_run
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
AfterRun hook
================================================================================
AfterRun
verify_run
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(word)))))
================================================================================
Hook with multiple statements
================================================================================
BeforeEach "complex setup"
export TEST_VAR="value"
mkdir -p /tmp/test
touch /tmp/test/file
End
--------------------------------------------------------------------------------
(program
(shellspec_hook_block
(command
name: (command_name
(string
(string_content))))
(declaration_command
(variable_assignment
name: (variable_name)
value: (string
(string_content))))
(command
name: (command_name
(word))
argument: (word)
argument: (word))
(command
name: (command_name
(word))
argument: (word))))

213
test/corpus/it_blocks.txt Normal file
View File

@@ -0,0 +1,213 @@
================================================================================
Basic It block
================================================================================
It "should work correctly"
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Example block
================================================================================
Example "example behavior"
echo "example"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Specify block
================================================================================
Specify "specific behavior"
echo "specify"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Focused It block
================================================================================
fIt "focused test"
echo "focused"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Focused Example block
================================================================================
fExample "focused example"
echo "focused"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Focused Specify block
================================================================================
fSpecify "focused specify"
echo "focused"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Skipped It block
================================================================================
xIt "skipped test"
echo "skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Skipped Example block
================================================================================
xExample "skipped example"
echo "skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Skipped Specify block
================================================================================
xSpecify "skipped specify"
echo "skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
It with complex assertions
================================================================================
It "should handle complex logic"
local result
result=$(some_function "param")
[ "$result" = "expected" ]
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (string
(string_content))
(declaration_command
(variable_name))
(variable_assignment
name: (variable_name)
value: (command_substitution
(command
name: (command_name
(word))
argument: (string
(string_content)))))
(test_command
(binary_expression
left: (string
(simple_expansion
(variable_name)))
right: (string
(string_content))))))

View File

@@ -0,0 +1,236 @@
================================================================================
Describe with Context
================================================================================
Describe "main feature"
Context "when condition A"
echo "setup A"
End
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(shellspec_context_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content))))))
================================================================================
Describe with It
================================================================================
Describe "main feature"
It "should work"
echo "test"
End
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content))))))
================================================================================
Context with It
================================================================================
Context "when ready"
It "should execute"
echo "executing"
End
End
--------------------------------------------------------------------------------
(program
(shellspec_context_block
description: (string
(string_content))
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))
argument: (string
(string_content))))))
================================================================================
Describe with hooks and tests
================================================================================
Describe "complete feature"
BeforeEach
setup_test
End
It "should work correctly"
run_test
End
AfterEach
cleanup_test
End
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(shellspec_hook_block
(command
name: (command_name
(word))))
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))))
(shellspec_hook_block
(command
name: (command_name
(word))))))
================================================================================
Complex nested structure
================================================================================
Describe "main functionality"
BeforeAll
global_setup
End
Context "when user is authenticated"
BeforeEach
login_user
End
It "should access protected resource"
access_resource
End
Context "and has admin privileges"
It "should access admin panel"
access_admin
End
End
AfterEach
logout_user
End
End
AfterAll
global_cleanup
End
End
--------------------------------------------------------------------------------
(program
(shellspec_describe_block
description: (string
(string_content))
(shellspec_hook_block
(command
name: (command_name
(word))))
(shellspec_context_block
description: (string
(string_content))
(shellspec_hook_block
(command
name: (command_name
(word))))
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word))))
(shellspec_context_block
description: (string
(string_content))
(shellspec_it_block
description: (string
(string_content))
(command
name: (command_name
(word)))))
(shellspec_hook_block
(command
name: (command_name
(word)))))
(shellspec_hook_block
(command
name: (command_name
(word))))))
================================================================================
Mixed with regular bash
================================================================================
#!/bin/bash
function helper() {
echo "helper function"
}
Describe "using bash functions"
It "should call helper"
result=$(helper)
echo "$result"
End
End
--------------------------------------------------------------------------------
(program
(comment)
(function_definition
name: (word)
body: (compound_statement
(command
name: (command_name
(word))
argument: (string
(string_content)))))
(shellspec_describe_block
description: (string
(string_content))
(shellspec_it_block
description: (string
(string_content))
(variable_assignment
name: (variable_name)
value: (command_substitution
(command
name: (command_name
(word)))))
(command
name: (command_name
(word))
argument: (string
(simple_expansion
(variable_name)))))))

View File

@@ -0,0 +1,102 @@
================================================================================
Before hook statements
================================================================================
Before 'setup'
--------------------------------------------------------------------------------
(program
(shellspec_hook_statement
argument: (raw_string)))
================================================================================
After hook with multiple arguments
================================================================================
Before 'setup1' 'setup2'
--------------------------------------------------------------------------------
(program
(shellspec_hook_statement
argument: (raw_string)
argument: (raw_string)))
================================================================================
Include directive
================================================================================
Include ./lib.sh
--------------------------------------------------------------------------------
(program
(shellspec_directive_statement
path: (word)))
================================================================================
Skip with conditional
================================================================================
Skip if "function returns success" conditions
--------------------------------------------------------------------------------
(program
(shellspec_directive_statement
reason: (string
(string_content))
condition: (word)))
================================================================================
Skip with complex conditional
================================================================================
Skip if 'function returns "skip"' [ "$(conditions)" = "skip" ]
--------------------------------------------------------------------------------
(program
(ERROR
(command
name: (command_name
(raw_string))
argument: (word)
argument: (string
(command_substitution
(command
name: (command_name
(word)))))
argument: (word)
argument: (string
(string_content))
argument: (word))))
================================================================================
Top-level It without Describe
================================================================================
It 'is simple'
When call echo 'ok'
The output should eq 'ok'
End
--------------------------------------------------------------------------------
(program
(shellspec_it_block
description: (raw_string)
(command
name: (command_name
(word))
argument: (word)
argument: (word)
argument: (raw_string))
(command
name: (command_name
(word))
argument: (word)
argument: (word)
argument: (word)
argument: (raw_string))))

View File

@@ -0,0 +1,258 @@
================================================================================
Data block
================================================================================
Data
item1
item2
item3
End
--------------------------------------------------------------------------------
(program
(shellspec_data_block
statements: (command
name: (command_name
(word)))
statements: (command
name: (command_name
(word)))
statements: (command
name: (command_name
(word)))))
================================================================================
Data block with label
================================================================================
Data "test data"
"value 1"
"value 2"
End
--------------------------------------------------------------------------------
(program
(shellspec_data_block
statements: (command
name: (command_name
(string
(string_content))))
statements: (command
name: (command_name
(string
(string_content))))
statements: (command
name: (command_name
(string
(string_content))))))
================================================================================
Parameters block
================================================================================
Parameters
param1
param2
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
(command
name: (command_name
(word)))
(command
name: (command_name
(word)))))
================================================================================
Parameters with label
================================================================================
Parameters "test parameters"
"first param"
"second param"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(string
(string_content))))))
================================================================================
Skip block
================================================================================
Skip
echo "this is skipped"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
label: (word)
(command
name: (command_name
(string
(string_content))))))
================================================================================
Skip with reason
================================================================================
Skip "not implemented yet"
echo "this test"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Pending block
================================================================================
Pending
echo "pending implementation"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
label: (word)
(command
name: (command_name
(string
(string_content))))))
================================================================================
Pending with reason
================================================================================
Pending "waiting for fix"
echo "test"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Todo block
================================================================================
Todo
echo "todo item"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
label: (word)
(command
name: (command_name
(string
(string_content))))))
================================================================================
Todo with description
================================================================================
Todo "implement feature X"
echo "feature X"
End
--------------------------------------------------------------------------------
(program
(shellspec_utility_block
(command
name: (command_name
(string
(string_content))))
(command
name: (command_name
(word))
argument: (string
(string_content)))))
================================================================================
Empty utility block
================================================================================
Data "empty data"
End
--------------------------------------------------------------------------------
(program
(shellspec_data_block
statements: (command
name: (command_name
(string
(string_content))))))
================================================================================
Data string argument style
================================================================================
Data "inline data"
--------------------------------------------------------------------------------
(program
(shellspec_data_block
argument: (string
(string_content))))
================================================================================
Data function argument style
================================================================================
Data get_test_data
--------------------------------------------------------------------------------
(program
(shellspec_data_block
argument: (word)))