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
|
path: ~/.npm/_npx
|
||||||
key: ${{ runner.os }}-tree-sitter-cli-${{ hashFiles('package.json') }}
|
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
|
- name: Cache Generated Grammar
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||||
id: cache-grammar
|
id: cache-grammar
|
||||||
|
|||||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -56,10 +56,6 @@ jobs:
|
|||||||
path: ~/.npm/_npx
|
path: ~/.npm/_npx
|
||||||
key: ${{ runner.os }}-tree-sitter-cli-${{ hashFiles('package.json') }}
|
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
|
- name: Cache Generated Grammar
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||||
id: cache-grammar
|
id: cache-grammar
|
||||||
@@ -128,7 +124,7 @@ jobs:
|
|||||||
End
|
End
|
||||||
EOF
|
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"
|
echo "❌ Parser failed on sample ShellSpec code"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Current Status: PRODUCTION READY ✅
|
## 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
|
## 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
|
and comprehensive tooling, it represents a high-quality open source project
|
||||||
ready for immediate use in development workflows and editor integrations.
|
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.
|
**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 blocks with advanced syntax support
|
||||||
shellspec_data_block: ($) =>
|
shellspec_data_block: ($) =>
|
||||||
choice(
|
choice(
|
||||||
// Block style with #| lines
|
// Block style with #| lines - highest precedence to ensure #| lines are parsed correctly
|
||||||
prec.right(
|
prec.right(
|
||||||
4,
|
5,
|
||||||
seq(
|
seq(
|
||||||
"Data",
|
"Data",
|
||||||
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
||||||
@@ -140,9 +140,9 @@ module.exports = grammar(bashGrammar, {
|
|||||||
"End",
|
"End",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Block style with regular statements - highest precedence to ensure End is captured
|
// Block style with regular statements
|
||||||
prec.right(
|
prec.right(
|
||||||
5,
|
4,
|
||||||
seq(
|
seq(
|
||||||
"Data",
|
"Data",
|
||||||
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
optional(seq(":", field("modifier", choice("raw", "expand")))),
|
||||||
|
|||||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -14,7 +14,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"markdownlint-cli": "^0.42.0",
|
"markdownlint-cli": "^0.42.0",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"tree-sitter-cli": "^0.24.2"
|
"tree-sitter-cli": "^0.25.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@isaacs/balanced-match": {
|
"node_modules/@isaacs/balanced-match": {
|
||||||
@@ -1095,9 +1095,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tree-sitter-cli": {
|
"node_modules/tree-sitter-cli": {
|
||||||
"version": "0.24.7",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.9.tgz",
|
||||||
"integrity": "sha512-o4gnE82pVmMMhJbWwD6+I9yr4lXii5Ci5qEQ2pFpUbVy1YiD8cizTJaqdcznA0qEbo7l2OneI1GocChPrI4YGQ==",
|
"integrity": "sha512-xcS2EJlNdwG529/JcYl5jV0ew/wY+HXvyNe8nkqhDCwQqxCH7odc9oLKxIWePQqmIKgieZ0YaGyieYKQI3MTKQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"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",
|
"clean": "rm -rf src/parser.c src/grammar.json src/node-types.json",
|
||||||
"rebuild": "npm run clean && npm run generate"
|
"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": {
|
"dependencies": {
|
||||||
"tree-sitter-bash": "^0.25.0"
|
"tree-sitter-bash": "^0.25.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"markdownlint-cli": "^0.42.0",
|
"markdownlint-cli": "^0.42.0",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"tree-sitter-cli": "^0.24.2"
|
"tree-sitter-cli": "^0.25.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7353,7 +7353,7 @@
|
|||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 4,
|
"value": 5,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
@@ -7465,7 +7465,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "PREC_RIGHT",
|
"type": "PREC_RIGHT",
|
||||||
"value": 5,
|
"value": 4,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
@@ -8014,5 +8014,6 @@
|
|||||||
"_statement",
|
"_statement",
|
||||||
"_expression",
|
"_expression",
|
||||||
"_primary_expression"
|
"_primary_expression"
|
||||||
]
|
],
|
||||||
}
|
"reserved": {}
|
||||||
|
}
|
||||||
@@ -3114,7 +3114,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "comment",
|
"type": "comment",
|
||||||
"named": true
|
"named": true,
|
||||||
|
"extra": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "declare",
|
"type": "declare",
|
||||||
@@ -3328,4 +3329,4 @@
|
|||||||
"type": "~",
|
"type": "~",
|
||||||
"named": false
|
"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 TSSymbol;
|
||||||
typedef uint16_t TSFieldId;
|
typedef uint16_t TSFieldId;
|
||||||
typedef struct TSLanguage TSLanguage;
|
typedef struct TSLanguage TSLanguage;
|
||||||
|
typedef struct TSLanguageMetadata {
|
||||||
|
uint8_t major_version;
|
||||||
|
uint8_t minor_version;
|
||||||
|
uint8_t patch_version;
|
||||||
|
} TSLanguageMetadata;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -26,10 +31,11 @@ typedef struct {
|
|||||||
bool inherited;
|
bool inherited;
|
||||||
} TSFieldMapEntry;
|
} TSFieldMapEntry;
|
||||||
|
|
||||||
|
// Used to index the field and supertype maps.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
} TSFieldMapSlice;
|
} TSMapSlice;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool visible;
|
bool visible;
|
||||||
@@ -79,6 +85,12 @@ typedef struct {
|
|||||||
uint16_t external_lex_state;
|
uint16_t external_lex_state;
|
||||||
} TSLexMode;
|
} TSLexMode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t lex_state;
|
||||||
|
uint16_t external_lex_state;
|
||||||
|
uint16_t reserved_word_set_id;
|
||||||
|
} TSLexerMode;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
TSParseAction action;
|
TSParseAction action;
|
||||||
struct {
|
struct {
|
||||||
@@ -93,7 +105,7 @@ typedef struct {
|
|||||||
} TSCharacterRange;
|
} TSCharacterRange;
|
||||||
|
|
||||||
struct TSLanguage {
|
struct TSLanguage {
|
||||||
uint32_t version;
|
uint32_t abi_version;
|
||||||
uint32_t symbol_count;
|
uint32_t symbol_count;
|
||||||
uint32_t alias_count;
|
uint32_t alias_count;
|
||||||
uint32_t token_count;
|
uint32_t token_count;
|
||||||
@@ -109,13 +121,13 @@ struct TSLanguage {
|
|||||||
const TSParseActionEntry *parse_actions;
|
const TSParseActionEntry *parse_actions;
|
||||||
const char * const *symbol_names;
|
const char * const *symbol_names;
|
||||||
const char * const *field_names;
|
const char * const *field_names;
|
||||||
const TSFieldMapSlice *field_map_slices;
|
const TSMapSlice *field_map_slices;
|
||||||
const TSFieldMapEntry *field_map_entries;
|
const TSFieldMapEntry *field_map_entries;
|
||||||
const TSSymbolMetadata *symbol_metadata;
|
const TSSymbolMetadata *symbol_metadata;
|
||||||
const TSSymbol *public_symbol_map;
|
const TSSymbol *public_symbol_map;
|
||||||
const uint16_t *alias_map;
|
const uint16_t *alias_map;
|
||||||
const TSSymbol *alias_sequences;
|
const TSSymbol *alias_sequences;
|
||||||
const TSLexMode *lex_modes;
|
const TSLexerMode *lex_modes;
|
||||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||||
TSSymbol keyword_capture_token;
|
TSSymbol keyword_capture_token;
|
||||||
@@ -129,15 +141,23 @@ struct TSLanguage {
|
|||||||
void (*deserialize)(void *, const char *, unsigned);
|
void (*deserialize)(void *, const char *, unsigned);
|
||||||
} external_scanner;
|
} external_scanner;
|
||||||
const TSStateId *primary_state_ids;
|
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 index = 0;
|
||||||
uint32_t size = len - index;
|
uint32_t size = len - index;
|
||||||
while (size > 1) {
|
while (size > 1) {
|
||||||
uint32_t half_size = size / 2;
|
uint32_t half_size = size / 2;
|
||||||
uint32_t mid_index = index + half_size;
|
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) {
|
if (lookahead >= range->start && lookahead <= range->end) {
|
||||||
return true;
|
return true;
|
||||||
} else if (lookahead > range->end) {
|
} else if (lookahead > range->end) {
|
||||||
@@ -145,7 +165,7 @@ static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t
|
|||||||
}
|
}
|
||||||
size -= half_size;
|
size -= half_size;
|
||||||
}
|
}
|
||||||
TSCharacterRange *range = &ranges[index];
|
const TSCharacterRange *range = &ranges[index];
|
||||||
return (lookahead >= range->start && lookahead <= range->end);
|
return (lookahead >= range->start && lookahead <= range->end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user