diff --git a/.github/workflows/format-apply.yml b/.github/workflows/format-apply.yml new file mode 100644 index 00000000..aea5dd68 --- /dev/null +++ b/.github/workflows/format-apply.yml @@ -0,0 +1,99 @@ +name: Format Apply + +on: + workflow_run: + workflows: ["Format Check"] + types: [completed] + +jobs: + suggest: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + permissions: + contents: read + pull-requests: write + + steps: + - name: Download diff artifact + uses: actions/download-artifact@v4 + with: + name: format-diff + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + path: ${{ runner.temp }}/format-diff + + - name: Read PR metadata + id: meta + run: | + echo "number=$(jq -r '.pull_request.number' ${{ runner.temp }}/format-diff/pr-event.json)" >> "$GITHUB_OUTPUT" + echo "sha=$(jq -r '.pull_request.head.sha' ${{ runner.temp }}/format-diff/pr-event.json)" >> "$GITHUB_OUTPUT" + + - name: Post suggestion comments + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DIFF_FILE: ${{ runner.temp }}/format-diff/format.diff + PR: ${{ steps.meta.outputs.number }} + REPO: ${{ github.repository }} + COMMIT: ${{ steps.meta.outputs.sha }} + run: | + python3 <<'PY' + import json, os, re, subprocess, sys + + with open(os.environ["DIFF_FILE"]) as f: + lines = f.read().splitlines() + + repo = os.environ["REPO"] + pr = os.environ["PR"] + commit = os.environ["COMMIT"] + endpoint = f"/repos/{repo}/pulls/{pr}/comments" + + def post(comment): + r = subprocess.run( + ["gh", "api", endpoint, "-X", "POST", "--input", "-"], + input=json.dumps(comment), text=True, capture_output=True, + ) + if r.returncode != 0: + print(f"skip ({r.stderr.strip()})", file=sys.stderr) + + path = None + i = 0 + posted = 0 + while i < len(lines): + line = lines[i] + if line.startswith("+++ b/"): + path = line[6:] + i += 1 + elif line.startswith("@@"): + m = re.match(r"@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@", line) + if not m: + i += 1; continue + old_start = int(m.group(1)) + old_count = int(m.group(2) or "1") + end_line = old_start + old_count - 1 + new_content = [] + i += 1 + while i < len(lines) and not lines[i].startswith("@@") and not lines[i].startswith("diff "): + l = lines[i] + if l.startswith("+") and not l.startswith("+++"): + new_content.append(l[1:]) + elif l.startswith(" "): + new_content.append(l[1:]) + i += 1 + body = "```suggestion\n" + "\n".join(new_content) + "\n```" + comment = { + "body": body, + "commit_id": commit, + "path": path, + "line": end_line, + "side": "RIGHT", + } + if end_line > old_start: + comment["start_line"] = old_start + comment["start_side"] = "RIGHT" + post(comment) + posted += 1 + else: + i += 1 + + print(f"attempted {posted} suggestion comment(s)") + PY diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 85a91e23..aae73a54 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -11,13 +11,13 @@ jobs: format: runs-on: ubuntu-latest permissions: - contents: write + contents: read steps: - name: Checkout code uses: actions/checkout@v6 - - name: Setup LLVM 22 + - name: Setup LLVM uses: ZhongRuoyu/setup-llvm@v0 with: llvm-version: 22 @@ -50,11 +50,27 @@ jobs: cargo fmt --manifest-path libcc2rs/Cargo.toml find tests -name '*.rs' -print0 | xargs -0 rustfmt - - name: Commit auto-fixes - if: github.ref != 'refs/heads/master' - uses: stefanzweifel/git-auto-commit-action@v5 + - name: Capture diff for later suggestion posting + id: diff + if: github.event_name == 'pull_request' + run: | + git diff > /tmp/format.diff + cp "$GITHUB_EVENT_PATH" /tmp/pr-event.json + if [ -s /tmp/format.diff ]; then + echo "has_diff=true" >> "$GITHUB_OUTPUT" + else + echo "has_diff=false" >> "$GITHUB_OUTPUT" + fi + + - name: Upload diff artifact + if: github.event_name == 'pull_request' && steps.diff.outputs.has_diff == 'true' + uses: actions/upload-artifact@v4 with: - commit_message: "Automatically apply formatting and lint fixes" + name: format-diff + path: | + /tmp/format.diff + /tmp/pr-event.json + retention-days: 1 - name: Check C++ formatting run: find cpp2rust tests -name '*.cpp' -o -name '*.h' -o -name '*.c' | xargs clang-format --dry-run --Werror diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 359210aa..18062284 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include +#include #include "compiler.h" #include "converter/converter_lib.h"