diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..a82092e --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,29 @@ +on: + workflow_dispatch: + pull_request: + push: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install modules + run: npm install + - name: Run ESLint + run: npm run lint + + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - run: npm install + - run: npm test + - run: tree-sitter parse test/*.just diff --git a/README.md b/README.md index fabc681..7286eed 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,10 @@ require"nvim-treesitter.install".compilers = {"gcc-11"} Building locally: -``` +```sh +# Create autogenerated files npm run gen +# Run tests npm run test tree-sitter parse test/test.just ``` diff --git a/package.json b/package.json index a04f223..a6b9027 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "grammar.js", "scripts": { "test": "tree-sitter test", - "gen": "tree-sitter generate" + "gen": "tree-sitter generate", + "lint": "eslint grammar.js" }, "repository": { "type": "git", @@ -24,6 +25,8 @@ "tree-sitter": "^0.19.0" }, "devDependencies": { + "eslint": "^8.51.0", + "eslint-config-google": "^0.14.0", "tree-sitter-cli": "^0.19.3" }, "tree-sitter": [ diff --git a/test/corpus/recipes.txt b/test/corpus/recipes.txt new file mode 100644 index 0000000..341ce1e --- /dev/null +++ b/test/corpus/recipes.txt @@ -0,0 +1,238 @@ +================================================================================ +recipe +================================================================================ + +foo: + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME)) + (NEWLINE) + (body + (INDENT) + (recipe_body + (line + (recipeline + (notcomment) + (NEWLINE)))) + (MISSING DEDENT))))) + +================================================================================ +quiet +================================================================================ + +@foo: + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME)) + (NEWLINE) + (body + (INDENT) + (recipe_body + (line + (recipeline + (notcomment) + (NEWLINE)))) + (MISSING DEDENT))))) + +================================================================================ +dependencies +================================================================================ + +foo: bar baz + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME) + (dependencies + (dependency + (NAME)) + (dependency + (NAME)))) + (NEWLINE) + (body + (INDENT) + (recipe_body + (line + (recipeline + (notcomment) + (NEWLINE)))) + (MISSING DEDENT))))) + +================================================================================ +arguments +================================================================================ + +foo bar *baz: + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME) + (parameters + (parameter + (NAME)) + (variadic_parameters + (parameter + (NAME))))) + (NEWLINE) + (body + (INDENT) + (recipe_body + (line + (recipeline + (notcomment) + (NEWLINE)))) + (MISSING DEDENT))))) + +================================================================================ +dependency expression +================================================================================ + +foo +bar: baz(bar) + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME) + (parameters + (parameter + (MISSING NAME)) + (variadic_parameters + (parameter + (NAME)))) + (dependencies + (dependency + (NAME)) + (dependency + (depcall + (NAME))))) + (NEWLINE) + (body + (INDENT) + (recipe_body + (line + (recipeline + (notcomment) + (NEWLINE)))) + (MISSING DEDENT))))) + +================================================================================ +attribute FIXME(attributes): XFAIL no attribute support +================================================================================ + +[attribute] +foo: + body + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (ERROR + (INDENT) + (NAME)) + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME)) + (NEWLINE))) + (ERROR + (NAME)) + (item + (eol + (NEWLINE)))) + + +================================================================================ +shebang +================================================================================ + +foo: + #!/bin/sh + if [ -f "foo" ]; then + echo "foo {{var}}" + fi + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (recipe + (recipeheader + (NAME)) + (NEWLINE) + (body + (INDENT) + (shebang_recipe + (shebang + (TEXT) + (NEWLINE)) + (shebang_body + (line + (recipeline + (notcomment) + (TEXT) + (TEXT) + (TEXT) + (TEXT) + (TEXT) + (NEWLINE))) + (line + (recipeline + (notcomment) + (TEXT) + (TEXT) + (NEWLINE))) + (line + (recipeline + (notcomment) + (NEWLINE))))) + (DEDENT))))) diff --git a/test/corpus/statements.txt b/test/corpus/statements.txt new file mode 100644 index 0000000..97d6045 --- /dev/null +++ b/test/corpus/statements.txt @@ -0,0 +1,394 @@ +================================================================================ +assignment +================================================================================ + +foo := "abc" + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (assignment + (NAME) + (expression + (value + (string + (STRING)))) + (eol + (NEWLINE))))) + +================================================================================ +expression +================================================================================ + +foo := "abc" + 'def' + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (assignment + (NAME) + (expression + (value + (string + (STRING))) + (expression + (value + (string + (RAW_STRING))))) + (eol + (NEWLINE))))) + + +================================================================================ +paths FIXME(paths) XFAIL from path operator +================================================================================ + +relative := "abc" / 'def' +absolute := / "abc" +combined := "foo" / bar() / baz + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (assignment + (NAME) + (expression + (value + (string + (STRING)))) + (ERROR + (INDENT) + (UNEXPECTED ') + (RAW_STRING)) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (ERROR + (UNEXPECTED ')) + (expression + (value + (NAME))) + (ERROR) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (ERROR + (value + (string + (STRING))) + (UNEXPECTED ') + (value + (call + (NAME))) + (UNEXPECTED ')) + (expression + (value + (NAME))) + (eol + (NEWLINE))))) + +================================================================================ +strings FIXME(escapes) XFAIL from escapes +================================================================================ + +foo := "a" +bar := 'b' +baz := "c +d" +qux := """e +f""" +quux := '''g +h +i +''' +corge := "foo\"bar" + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (assignment + (NAME) + (expression + (value + (string + (STRING)))) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (expression + (value + (string + (RAW_STRING)))) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (expression + (value + (string + (STRING)))) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (expression + (value + (string + (INDENTED_STRING)))) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (expression + (value + (string + (INDENTED_RAW_STRING)))) + (eol + (NEWLINE)))) + (item + (assignment + (NAME) + (ERROR + (value + (string + (STRING)))) + (expression + (value + (NAME))) + (ERROR) + (eol + (NEWLINE))))) + +================================================================================ +if +================================================================================ + +foo := if a == "x" { + "val" +} else if "1" != "2" { foo_fn("val") } +} else { val } + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (ERROR + (NAME) + (condition + (expression + (value + (NAME))) + (expression + (value + (string + (STRING))))) + (ERROR + (expression + (value + (string + (STRING))))) + (expression + (condition + (expression + (value + (string + (STRING)))) + (expression + (value + (string + (STRING))))) + (expression + (value + (call + (NAME) + (sequence + (expression + (value + (string + (STRING)))))))) + (ERROR + (NEWLINE)) + (expression + (value + (NAME))))) + (item + (eol + (NEWLINE)))) + +================================================================================ +function +================================================================================ + +foo := some_fn("param1", param2) + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (assignment + (NAME) + (expression + (value + (call + (NAME) + (sequence + (expression + (value + (string + (STRING)))) + (sequence + (expression + (value + (NAME)))))))) + (eol + (NEWLINE))))) + +================================================================================ +export +================================================================================ + +export foo := "abc" + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (export + (assignment + (NAME) + (expression + (value + (string + (STRING)))) + (eol + (NEWLINE)))))) + +================================================================================ +modules FIXME(mod): XFAIL mod support +================================================================================ + +mod foo +mod bar 'PATH' + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (ERROR + (NAME) + (parameter + (NAME)) + (parameter + (NAME)) + (parameter + (NAME)) + (INDENT) + (RAW_STRING)) + (item + (eol + (NEWLINE)))) + +================================================================================ +set # FIXME(array): XFAIL arrays +================================================================================ + +set SOME_BOOL +set FOO := true +set dotenv-load +set shell := ["powershell.exe", "-c"] + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (setting + (NAME) + (eol + (NEWLINE)))) + (item + (setting + (NAME) + (boolean) + (eol + (NEWLINE)))) + (item + (setting + (NAME) + (eol + (NEWLINE)))) + (item + (setting + (NAME) + (ERROR + (INDENT) + (UNEXPECTED '.') + (NAME)) + (string + (STRING)) + (eol + (NEWLINE))))) + +================================================================================ +comment +================================================================================ + +# comment +foo := bar # + baz + +-------------------------------------------------------------------------------- + +(source_file + (item + (eol + (NEWLINE))) + (item + (eol + (comment + (NEWLINE)))) + (item + (assignment + (NAME) + (expression + (value + (NAME))) + (eol + (comment + (NEWLINE))))))