mirror of
https://github.com/ivuorinen/tree-sitter-shellspec.git
synced 2026-01-26 03:34:03 +00:00
refactor: enhance CI/CD workflows and apply CodeRabbit suggestions
- Convert GitHub Actions from local to inline actions for better maintainability - Add comprehensive caching for npm dependencies, tree-sitter CLI, and build artifacts - Fix checkout steps missing in test matrix jobs - Apply defensive programming in test coverage validation - Use local tree-sitter CLI via npx instead of global installation - Update tree-sitter-cli to v0.25.0 for compatibility with tree-sitter-bash - Add proper tree-sitter field to package.json with grammar metadata - Fix grammar precedence for Data blocks (#| lines now have higher precedence) - Standardize dates in memory files to September 12, 2025 - Enhance workflow robustness with dynamic workflow ID resolution - Improve test file pattern matching and error handling This commit addresses all CodeRabbit review suggestions and optimizes GitHub Actions workflows for better performance and reliability.
This commit is contained in:
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -170,9 +170,6 @@ jobs:
|
||||
path: ~/.npm/_npx
|
||||
key: ${{ runner.os }}-tree-sitter-cli-${{ hashFiles('package.json') }}
|
||||
|
||||
- name: Install Tree-sitter CLI
|
||||
run: npm install -g tree-sitter-cli
|
||||
|
||||
- name: Cache Generated Grammar
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
id: cache-grammar
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -56,10 +56,6 @@ jobs:
|
||||
path: ~/.npm/_npx
|
||||
key: ${{ runner.os }}-tree-sitter-cli-${{ hashFiles('package.json') }}
|
||||
|
||||
- name: Install Tree-sitter CLI
|
||||
run: npm install -g tree-sitter-cli
|
||||
shell: bash
|
||||
|
||||
- name: Cache Generated Grammar
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
id: cache-grammar
|
||||
@@ -128,7 +124,7 @@ jobs:
|
||||
End
|
||||
EOF
|
||||
|
||||
tree-sitter parse --language=shellspec test_sample.shellspec --quiet || {
|
||||
npx tree-sitter parse --language=shellspec test_sample.shellspec --quiet || {
|
||||
echo "❌ Parser failed on sample ShellSpec code"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Current Status: PRODUCTION READY ✅
|
||||
|
||||
This memory contains only verified, accurate information about the current project state as of September 2025.
|
||||
This memory contains only verified, accurate information about the current project state as of September 12, 2025.
|
||||
|
||||
## Core Project Facts
|
||||
|
||||
@@ -242,5 +242,5 @@ With 61/61 tests passing, zero grammar warnings, optimized CI/CD workflows,
|
||||
and comprehensive tooling, it represents a high-quality open source project
|
||||
ready for immediate use in development workflows and editor integrations.
|
||||
|
||||
**Last Verified**: December 2025
|
||||
**Last Verified**: September 12, 2025
|
||||
**Status**: All claims in this memory have been verified against the actual project state.
|
||||
|
||||
@@ -124,9 +124,9 @@ module.exports = grammar(bashGrammar, {
|
||||
// ShellSpec Data blocks with advanced syntax support
|
||||
shellspec_data_block: ($) =>
|
||||
choice(
|
||||
// Block style with #| lines
|
||||
// Block style with #| lines - highest precedence to ensure #| lines are parsed correctly
|
||||
prec.right(
|
||||
4,
|
||||
5,
|
||||
seq(
|
||||
"Data",
|
||||
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
||||
@@ -140,9 +140,9 @@ module.exports = grammar(bashGrammar, {
|
||||
"End",
|
||||
),
|
||||
),
|
||||
// Block style with regular statements - highest precedence to ensure End is captured
|
||||
// Block style with regular statements
|
||||
prec.right(
|
||||
5,
|
||||
4,
|
||||
seq(
|
||||
"Data",
|
||||
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -14,7 +14,7 @@
|
||||
"devDependencies": {
|
||||
"markdownlint-cli": "^0.42.0",
|
||||
"nodemon": "^3.0.1",
|
||||
"tree-sitter-cli": "^0.24.2"
|
||||
"tree-sitter-cli": "^0.25.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
@@ -1095,9 +1095,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tree-sitter-cli": {
|
||||
"version": "0.24.7",
|
||||
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.24.7.tgz",
|
||||
"integrity": "sha512-o4gnE82pVmMMhJbWwD6+I9yr4lXii5Ci5qEQ2pFpUbVy1YiD8cizTJaqdcznA0qEbo7l2OneI1GocChPrI4YGQ==",
|
||||
"version": "0.25.9",
|
||||
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.9.tgz",
|
||||
"integrity": "sha512-xcS2EJlNdwG529/JcYl5jV0ew/wY+HXvyNe8nkqhDCwQqxCH7odc9oLKxIWePQqmIKgieZ0YaGyieYKQI3MTKQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
|
||||
13
package.json
13
package.json
@@ -20,12 +20,23 @@
|
||||
"clean": "rm -rf src/parser.c src/grammar.json src/node-types.json",
|
||||
"rebuild": "npm run clean && npm run generate"
|
||||
},
|
||||
"tree-sitter": [
|
||||
{
|
||||
"scope": "source.shellspec",
|
||||
"file-types": [
|
||||
"shellspec"
|
||||
],
|
||||
"path": ".",
|
||||
"grammar-path": "grammar.js",
|
||||
"highlights": "queries/highlights.scm"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"tree-sitter-bash": "^0.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"markdownlint-cli": "^0.42.0",
|
||||
"nodemon": "^3.0.1",
|
||||
"tree-sitter-cli": "^0.24.2"
|
||||
"tree-sitter-cli": "^0.25.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7353,7 +7353,7 @@
|
||||
"members": [
|
||||
{
|
||||
"type": "PREC_RIGHT",
|
||||
"value": 4,
|
||||
"value": 5,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
@@ -7465,7 +7465,7 @@
|
||||
},
|
||||
{
|
||||
"type": "PREC_RIGHT",
|
||||
"value": 5,
|
||||
"value": 4,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
@@ -8014,5 +8014,6 @@
|
||||
"_statement",
|
||||
"_expression",
|
||||
"_primary_expression"
|
||||
]
|
||||
}
|
||||
],
|
||||
"reserved": {}
|
||||
}
|
||||
@@ -3114,7 +3114,8 @@
|
||||
},
|
||||
{
|
||||
"type": "comment",
|
||||
"named": true
|
||||
"named": true,
|
||||
"extra": true
|
||||
},
|
||||
{
|
||||
"type": "declare",
|
||||
@@ -3328,4 +3329,4 @@
|
||||
"type": "~",
|
||||
"named": false
|
||||
}
|
||||
]
|
||||
]
|
||||
1488
src/parser.c
1488
src/parser.c
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,11 @@ typedef uint16_t TSStateId;
|
||||
typedef uint16_t TSSymbol;
|
||||
typedef uint16_t TSFieldId;
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
typedef struct TSLanguageMetadata {
|
||||
uint8_t major_version;
|
||||
uint8_t minor_version;
|
||||
uint8_t patch_version;
|
||||
} TSLanguageMetadata;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@@ -26,10 +31,11 @@ typedef struct {
|
||||
bool inherited;
|
||||
} TSFieldMapEntry;
|
||||
|
||||
// Used to index the field and supertype maps.
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} TSFieldMapSlice;
|
||||
} TSMapSlice;
|
||||
|
||||
typedef struct {
|
||||
bool visible;
|
||||
@@ -79,6 +85,12 @@ typedef struct {
|
||||
uint16_t external_lex_state;
|
||||
} TSLexMode;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lex_state;
|
||||
uint16_t external_lex_state;
|
||||
uint16_t reserved_word_set_id;
|
||||
} TSLexerMode;
|
||||
|
||||
typedef union {
|
||||
TSParseAction action;
|
||||
struct {
|
||||
@@ -93,7 +105,7 @@ typedef struct {
|
||||
} TSCharacterRange;
|
||||
|
||||
struct TSLanguage {
|
||||
uint32_t version;
|
||||
uint32_t abi_version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
@@ -109,13 +121,13 @@ struct TSLanguage {
|
||||
const TSParseActionEntry *parse_actions;
|
||||
const char * const *symbol_names;
|
||||
const char * const *field_names;
|
||||
const TSFieldMapSlice *field_map_slices;
|
||||
const TSMapSlice *field_map_slices;
|
||||
const TSFieldMapEntry *field_map_entries;
|
||||
const TSSymbolMetadata *symbol_metadata;
|
||||
const TSSymbol *public_symbol_map;
|
||||
const uint16_t *alias_map;
|
||||
const TSSymbol *alias_sequences;
|
||||
const TSLexMode *lex_modes;
|
||||
const TSLexerMode *lex_modes;
|
||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||
TSSymbol keyword_capture_token;
|
||||
@@ -129,15 +141,23 @@ struct TSLanguage {
|
||||
void (*deserialize)(void *, const char *, unsigned);
|
||||
} external_scanner;
|
||||
const TSStateId *primary_state_ids;
|
||||
const char *name;
|
||||
const TSSymbol *reserved_words;
|
||||
uint16_t max_reserved_word_set_size;
|
||||
uint32_t supertype_count;
|
||||
const TSSymbol *supertype_symbols;
|
||||
const TSMapSlice *supertype_map_slices;
|
||||
const TSSymbol *supertype_map_entries;
|
||||
TSLanguageMetadata metadata;
|
||||
};
|
||||
|
||||
static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
|
||||
static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
|
||||
uint32_t index = 0;
|
||||
uint32_t size = len - index;
|
||||
while (size > 1) {
|
||||
uint32_t half_size = size / 2;
|
||||
uint32_t mid_index = index + half_size;
|
||||
TSCharacterRange *range = &ranges[mid_index];
|
||||
const TSCharacterRange *range = &ranges[mid_index];
|
||||
if (lookahead >= range->start && lookahead <= range->end) {
|
||||
return true;
|
||||
} else if (lookahead > range->end) {
|
||||
@@ -145,7 +165,7 @@ static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t
|
||||
}
|
||||
size -= half_size;
|
||||
}
|
||||
TSCharacterRange *range = &ranges[index];
|
||||
const TSCharacterRange *range = &ranges[index];
|
||||
return (lookahead >= range->start && lookahead <= range->end);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user