cargo-macra 0.2.0

CLI for working with macro expansion and diagnostics in Rust projects.
Documentation
name: CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable

      - name: clippy
        run: cargo clippy --workspace --no-deps -- -D warnings

      - name: Generate docs
        env:
          RUSTDOCFLAGS: -D warnings
        run: cargo doc --workspace --all-features --no-deps
  test:
    name: Test ( ${{ matrix.os }} ${{ matrix.rust }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - windows-latest
          - macos-latest
          - macos-15-intel
        rust:
          - 1.86.0
          - 1.87.0
          - 1.88.0
          - 1.89.0
          - 1.90.0
          - 1.91.0
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          submodules: true

      - name: Install Rust ${{ matrix.rust }}
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}

      - name: Cache cargo registry and build artifacts
        uses: Swatinem/rust-cache@v2

      - name: remove Cargo.lock
        shell: bash
        run: rm -f Cargo.lock

      - name: Run tests
        run: cargo test --workspace --all-targets

      - name: Package and install from crate tarball
        shell: pwsh
        if: ${{ always() }}
        run: |
          cargo package --locked --allow-dirty

          $crate = Get-ChildItem "target/package/cargo-macra-*.crate" | Select-Object -First 1
          if (-not $crate) {
            throw "crate tarball was not generated"
          }

          $work = Get-Location
          $archive = Join-Path $env:RUNNER_TEMP "cargo-macra.crate"
          $src = Join-Path $env:RUNNER_TEMP "cargo-macra-src"
          Copy-Item $crate.FullName $archive -Force

          Get-ChildItem -Force $work |
            Where-Object { $_.Name -notin @(".", "..") } |
            Remove-Item -Recurse -Force

          New-Item -ItemType Directory -Path $src -Force | Out-Null
          tar -xf $archive -C $src
          $pkgDir = Get-ChildItem $src -Directory | Select-Object -First 1
          if (-not $pkgDir) {
            throw "failed to unpack crate source directory"
          }

          cargo install --path $pkgDir.FullName --locked --force

          # Create a minimal smoke-test project (tests/test-usage is not in the package)
          $testDir = Join-Path $env:RUNNER_TEMP "macra-smoke-test"
          New-Item -ItemType Directory -Path $testDir -Force | Out-Null
          @('[package]', 'name = "smoke-test"', 'version = "0.1.0"', 'edition = "2021"') |
            Set-Content -Path (Join-Path $testDir "Cargo.toml")
          New-Item -ItemType Directory -Path (Join-Path $testDir "src") -Force | Out-Null
          @('macro_rules! greet {', '    ($name:expr) => { format!("Hello, {}!", $name) };', '}', 'pub fn hello() -> String { greet!("world") }') |
            Set-Content -Path (Join-Path $testDir "src" "lib.rs")

          $showExpansion = cargo-macra --show-expansion --manifest-path (Join-Path $testDir "Cargo.toml") --lib 2>&1
          if ($LASTEXITCODE -ne 0) {
            $showExpansion | Out-Host
            throw "cargo-macra --show-expansion failed"
          }

          $requiredSnippets = @(
            "== greet! ==",
            '"world"',
            "---",
            'format! ("Hello, {}!", "world")'
          )

          foreach ($snippet in $requiredSnippets) {
            if (-not ($showExpansion | Select-String -SimpleMatch -Pattern $snippet)) {
              $showExpansion | Out-Host
              throw "Expected snippet not found in show-expansion output: $snippet"
            }
          }

      - name: Debug show-expansion for known failing external crates
        if: ${{ failure() }}
        shell: pwsh
        run: |
          $cases = @(
            @{ manifest = "tests/external_crates/coinduction/Cargo.toml"; test = "coinduction_integration_test" },
            @{ manifest = "tests/external_crates/coinduction/Cargo.toml"; test = "complex" },
            @{ manifest = "tests/external_crates/discriminant/Cargo.toml"; test = "test" },
            @{ manifest = "tests/external_crates/newer-type/Cargo.toml"; test = "multi_self" },
            @{ manifest = "tests/external_crates/parametrized/Cargo.toml"; test = "recursive" },
            @{ manifest = "tests/external_crates/parametrized/Cargo.toml"; test = "test" },
            @{ manifest = "tests/external_crates/parametrized/Cargo.toml"; test = "test_enum" },
            @{ manifest = "tests/external_crates/parametrized/Cargo.toml"; test = "tuple" }
          )

          foreach ($case in $cases) {
            Write-Host "=== show-expansion: manifest=$($case.manifest) test=$($case.test) ==="
            cargo run -- --show-expansion --manifest-path $case.manifest --test $case.test
            if ($LASTEXITCODE -ne 0) {
              Write-Host "show-expansion failed for manifest=$($case.manifest) test=$($case.test)"
            }
          }
          exit 0