name: Tree-Sitter CI

on:
  push:
    branches: [main]
    paths:
      - "**"
      - "!/*.md"
      - "!/LICENSE*"

  pull_request:
    paths:
      - "**"
      - "!/*.md"
      - "!/LICENSE*"

env:
  GRAMMAR_NAME: sdml
  BUILD_OUTPUT_DIR: build
  EXAMPLES_DIR: examples
  EM_VERSION: 4.0.16
  NODE_VERSION: 24

jobs:
  generate:
    name: Generate parser
    strategy:
      matrix:
        os: ["ubuntu-latest", "windows-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2
        with:
          install-lib: false

      - name: Run parser generator
        run: tree-sitter generate

  test:
    name: Run tests
    needs: [generate]
    strategy:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2

      - name: Run included tests
        uses: tree-sitter/parser-test-action@v3
        with:
          test-rust: true

  examples:
    name: Parse example files
    needs: [generate]
    strategy:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2

      - name: Parse example files
        uses: tree-sitter/parse-action@v4
        id: examples
        continue-on-error: true
        with:
          files: |-
            ${{ env.EXAMPLES_DIR }}/**

      - name: Upload errors
        uses: actions/upload-artifact@v4
        if: steps.examples.outputs.failures != ''
        with:
          name: failures
          path: ${{steps.examples.outputs.failures}}

  build-lib:
    name: Build parser library
    needs: [test]
    strategy:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Setup environment
        run: |-
          echo "BUILD_OUTPUT=${{ env.BUILD_OUTPUT_DIR }}/lib${{ env.GRAMMAR_NAME }}.so" >> "$GITHUB_ENV"
            
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2

      - name: Make output directory
        run: mkdir -p ${{ env.BUILD_OUTPUT_DIR }}

      - name: Build core library
        run: tree-sitter build --output "$BUILD_OUTPUT"

      - name: Upload output
        uses: actions/upload-artifact@v4
        with:
          name: Parser library (${{ matrix.os }})
          path: "$BUILD_OUTPUT"

  build-wasm:
    name: Build WASM bindings
    needs: [build-lib]
    strategy:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Setup environment
        run: |-
          echo "BUILD_OUTPUT=${{ env.BUILD_OUTPUT_DIR }}/${{ env.GRAMMAR_NAME }}.wasm" >> "$GITHUB_ENV"
            
      - name: Checkout repository
        uses: actions/checkout@v5

      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2

      - name: Setup Emscripten tooling
        uses: mymindstorm/setup-emsdk@v14
        with:
          version: ${{ env.EM_VERSION }}

      - name: Verify Emscripten install
        run: emcc --version

      - name: Make output directory
        run: mkdir -p ${{ env.BUILD_OUTPUT_DIR }}

      - name: Build wasm library
        run: tree-sitter build --wasm --output "$BUILD_OUTPUT"

      - name: Upload output
        uses: actions/upload-artifact@v4
        with:
          name: WASM library (${{ matrix.os }})
          path: "$BUILD_OUTPUT"

  test-bindings:
    name: Test all bindings
    needs: [build-lib]
    strategy:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
  
      - name: Setup tree-sitter tooling
        uses: tree-sitter/setup-action@v2
  
      - name: Run tests
        uses: tree-sitter/parser-test-action@v3
        with:
          test-rust: true
          test-node: true
          test-python: true
          test-go: true
          test-swift: true
          test-zig: false
  
      - name: Upload output
        uses: actions/upload-artifact@v4
        if: steps.examples.outputs.failures != ''
        with:
          name: failures-${{matrix.os}}
          path: ${{steps.examples.outputs.failures}}
