mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into redsun82/cargo-upgrade
This commit is contained in:
35
.github/workflows/go-tests-other-os.yml
vendored
35
.github/workflows/go-tests-other-os.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: "Go: Run Tests - Other OS"
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "go/**"
|
||||
- "!go/documentation/**"
|
||||
- "!go/ql/**" # don't run other-os if only ql/ files changed
|
||||
- .github/workflows/go-tests-other-os.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
- MODULE.bazel
|
||||
- .bazelrc
|
||||
- misc/bazel/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-mac:
|
||||
name: Test MacOS
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Run tests
|
||||
uses: ./go/actions/test
|
||||
|
||||
test-win:
|
||||
name: Test Windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Run tests
|
||||
uses: ./go/actions/test
|
||||
22
.github/workflows/go-tests-rtjo.yml
vendored
22
.github/workflows/go-tests-rtjo.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: "Go: Run RTJO Tests"
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-linux:
|
||||
if: "github.repository_owner == 'github' && github.event.label.name == 'Run: RTJO Language Tests'"
|
||||
name: RTJO Test Linux (Ubuntu)
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Run tests
|
||||
uses: ./go/actions/test
|
||||
with:
|
||||
run-code-checks: true
|
||||
dynamic-join-order-mode: all
|
||||
13
.github/workflows/go-tests.yml
vendored
13
.github/workflows/go-tests.yml
vendored
@@ -1,20 +1,9 @@
|
||||
name: "Go: Run Tests"
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "go/**"
|
||||
- "!go/documentation/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "go/**"
|
||||
- "!go/documentation/**"
|
||||
- "!go/documentation/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
|
||||
@@ -32,4 +32,8 @@ extensions:
|
||||
- ["", "", False, "CommandLineToArgvA", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
|
||||
- ["", "", False, "CommandLineToArgvW", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
|
||||
# fileapi.h
|
||||
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
|
||||
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
|
||||
# processthreadsapi.h
|
||||
- ["", "", False, "CreateThread", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
|
||||
- ["", "", False, "CreateRemoteThread", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
|
||||
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
|
||||
4
cpp/ql/src/change-notes/2025-07-12-create-thread.md
Normal file
4
cpp/ql/src/change-notes/2025-07-12-create-thread.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.
|
||||
@@ -17,13 +17,16 @@ models
|
||||
| 16 | Source: ; ; false; ymlSource; ; ; ReturnValue; local; manual |
|
||||
| 17 | Source: boost::asio; ; false; read_until; ; ; Argument[*1]; remote; manual |
|
||||
| 18 | Summary: ; ; false; CommandLineToArgvA; ; ; Argument[*0]; ReturnValue[**]; taint; manual |
|
||||
| 19 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
|
||||
| 20 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
|
||||
| 21 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 22 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 23 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
| 19 | Summary: ; ; false; CreateRemoteThread; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
|
||||
| 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
|
||||
| 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
|
||||
| 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
|
||||
| 23 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
|
||||
| 24 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 25 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 26 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
edges
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:23 |
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:26 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
|
||||
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
|
||||
@@ -32,10 +35,10 @@ edges
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:23 |
|
||||
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:21 |
|
||||
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:20 |
|
||||
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:22 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:26 |
|
||||
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:24 |
|
||||
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:23 |
|
||||
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:25 |
|
||||
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
|
||||
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
|
||||
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
|
||||
@@ -47,15 +50,15 @@ edges
|
||||
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
|
||||
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:21 |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:24 |
|
||||
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
|
||||
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:20 |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:23 |
|
||||
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
|
||||
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:22 |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:25 |
|
||||
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
|
||||
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
|
||||
@@ -73,8 +76,8 @@ edges
|
||||
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | windows.cpp:41:10:41:13 | * ... | provenance | Src:MaD:5 |
|
||||
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | provenance | |
|
||||
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | provenance | |
|
||||
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:19 |
|
||||
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:19 |
|
||||
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:22 |
|
||||
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:22 |
|
||||
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | provenance | |
|
||||
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | provenance | |
|
||||
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | provenance | |
|
||||
@@ -122,6 +125,29 @@ edges
|
||||
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | provenance | Src:MaD:12 |
|
||||
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:333:20:333:52 | *pMapView | provenance | |
|
||||
| windows.cpp:333:20:333:52 | *pMapView | windows.cpp:335:10:335:16 | * ... | provenance | |
|
||||
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | provenance | MaD:21 |
|
||||
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | windows.cpp:403:26:403:36 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | provenance | MaD:19 |
|
||||
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | windows.cpp:410:26:410:36 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | provenance | MaD:20 |
|
||||
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | windows.cpp:417:26:417:36 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:403:26:403:36 | *lpParameter [x] | windows.cpp:405:10:405:25 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:405:10:405:25 | *lpParameter [x] | windows.cpp:406:8:406:8 | *s [x] | provenance | |
|
||||
| windows.cpp:406:8:406:8 | *s [x] | windows.cpp:406:8:406:11 | x | provenance | |
|
||||
| windows.cpp:410:26:410:36 | *lpParameter [x] | windows.cpp:412:10:412:25 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:412:10:412:25 | *lpParameter [x] | windows.cpp:413:8:413:8 | *s [x] | provenance | |
|
||||
| windows.cpp:413:8:413:8 | *s [x] | windows.cpp:413:8:413:11 | x | provenance | |
|
||||
| windows.cpp:417:26:417:36 | *lpParameter [x] | windows.cpp:419:10:419:25 | *lpParameter [x] | provenance | |
|
||||
| windows.cpp:419:10:419:25 | *lpParameter [x] | windows.cpp:420:8:420:8 | *s [x] | provenance | |
|
||||
| windows.cpp:420:8:420:8 | *s [x] | windows.cpp:420:8:420:11 | x | provenance | |
|
||||
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:439:7:439:8 | *& ... [x] | provenance | |
|
||||
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:451:7:451:8 | *& ... [x] | provenance | |
|
||||
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:464:7:464:8 | *& ... [x] | provenance | |
|
||||
| windows.cpp:431:3:431:16 | ... = ... | windows.cpp:431:3:431:3 | *s [post update] [x] | provenance | |
|
||||
| windows.cpp:431:9:431:14 | call to source | windows.cpp:431:3:431:16 | ... = ... | provenance | |
|
||||
| windows.cpp:439:7:439:8 | *& ... [x] | windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | provenance | |
|
||||
| windows.cpp:451:7:451:8 | *& ... [x] | windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | provenance | |
|
||||
| windows.cpp:464:7:464:8 | *& ... [x] | windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | provenance | |
|
||||
nodes
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
|
||||
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
|
||||
@@ -238,6 +264,30 @@ nodes
|
||||
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
|
||||
| windows.cpp:333:20:333:52 | *pMapView | semmle.label | *pMapView |
|
||||
| windows.cpp:335:10:335:16 | * ... | semmle.label | * ... |
|
||||
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | semmle.label | [summary param] *3 in CreateThread [x] |
|
||||
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] |
|
||||
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | semmle.label | [summary param] *4 in CreateRemoteThread [x] |
|
||||
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] |
|
||||
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | semmle.label | [summary param] *4 in CreateRemoteThreadEx [x] |
|
||||
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] |
|
||||
| windows.cpp:403:26:403:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:405:10:405:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:406:8:406:8 | *s [x] | semmle.label | *s [x] |
|
||||
| windows.cpp:406:8:406:11 | x | semmle.label | x |
|
||||
| windows.cpp:410:26:410:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:412:10:412:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:413:8:413:8 | *s [x] | semmle.label | *s [x] |
|
||||
| windows.cpp:413:8:413:11 | x | semmle.label | x |
|
||||
| windows.cpp:417:26:417:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:419:10:419:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
|
||||
| windows.cpp:420:8:420:8 | *s [x] | semmle.label | *s [x] |
|
||||
| windows.cpp:420:8:420:11 | x | semmle.label | x |
|
||||
| windows.cpp:431:3:431:3 | *s [post update] [x] | semmle.label | *s [post update] [x] |
|
||||
| windows.cpp:431:3:431:16 | ... = ... | semmle.label | ... = ... |
|
||||
| windows.cpp:431:9:431:14 | call to source | semmle.label | call to source |
|
||||
| windows.cpp:439:7:439:8 | *& ... [x] | semmle.label | *& ... [x] |
|
||||
| windows.cpp:451:7:451:8 | *& ... [x] | semmle.label | *& ... [x] |
|
||||
| windows.cpp:464:7:464:8 | *& ... [x] | semmle.label | *& ... [x] |
|
||||
subpaths
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |
|
||||
|
||||
@@ -4638,7 +4638,13 @@
|
||||
| Dubious signature "(z_streamp,int *)" in summary model. |
|
||||
| Dubious signature "(z_streamp,unsigned int *,int *)" in summary model. |
|
||||
| Dubious signature "(z_streamp,unsigned int)" in summary model. |
|
||||
| Unrecognized input specification "Argument[***3]" in summary model. |
|
||||
| Unrecognized input specification "Argument[***4]" in summary model. |
|
||||
| Unrecognized input specification "Argument[****3]" in summary model. |
|
||||
| Unrecognized input specification "Argument[****4]" in summary model. |
|
||||
| Unrecognized input specification "Field[****hEvent]" in summary model. |
|
||||
| Unrecognized input specification "Field[***hEvent]" in summary model. |
|
||||
| Unrecognized output specification "Field[****hEvent]" in summary model. |
|
||||
| Unrecognized output specification "Field[***hEvent]" in summary model. |
|
||||
| Unrecognized output specification "Parameter[***0]" in summary model. |
|
||||
| Unrecognized output specification "Parameter[****0]" in summary model. |
|
||||
|
||||
@@ -335,3 +335,135 @@ void mapViewOfFile(HANDLE hMapFile) {
|
||||
sink(*buffer); // $ ir
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _SECURITY_ATTRIBUTES
|
||||
{
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
|
||||
|
||||
typedef DWORD (*LPTHREAD_START_ROUTINE)(
|
||||
LPVOID lpThreadParameter);
|
||||
|
||||
HANDLE CreateThread(
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
SIZE_T dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId);
|
||||
|
||||
HANDLE CreateRemoteThread(
|
||||
HANDLE hProcess,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
SIZE_T dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId
|
||||
);
|
||||
|
||||
typedef ULONG_PTR DWORD_PTR;
|
||||
|
||||
typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
|
||||
{
|
||||
DWORD_PTR Attribute;
|
||||
SIZE_T cbSize;
|
||||
PVOID lpValue;
|
||||
} PROC_THREAD_ATTRIBUTE_ENTRY, *LPPROC_THREAD_ATTRIBUTE_ENTRY;
|
||||
|
||||
// This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
|
||||
typedef struct _PROC_THREAD_ATTRIBUTE_LIST
|
||||
{
|
||||
DWORD dwFlags;
|
||||
ULONG Size;
|
||||
ULONG Count;
|
||||
ULONG Reserved;
|
||||
PULONG Unknown;
|
||||
PROC_THREAD_ATTRIBUTE_ENTRY Entries[1];
|
||||
} PROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
|
||||
|
||||
HANDLE CreateRemoteThreadEx(
|
||||
HANDLE hProcess,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
SIZE_T dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
|
||||
LPDWORD lpThreadId
|
||||
);
|
||||
|
||||
struct S
|
||||
{
|
||||
int x;
|
||||
};
|
||||
|
||||
DWORD ThreadProc1(LPVOID lpParameter)
|
||||
{
|
||||
S *s = (S *)lpParameter;
|
||||
sink(s->x); // $ ir
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD ThreadProc2(LPVOID lpParameter)
|
||||
{
|
||||
S *s = (S *)lpParameter;
|
||||
sink(s->x); // $ ir
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD ThreadProc3(LPVOID lpParameter)
|
||||
{
|
||||
S *s = (S *)lpParameter;
|
||||
sink(s->x); // $ ir
|
||||
return 0;
|
||||
}
|
||||
|
||||
int source();
|
||||
|
||||
void test_create_thread()
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
|
||||
S s;
|
||||
s.x = source();
|
||||
|
||||
{
|
||||
DWORD threadId;
|
||||
HANDLE threadHandle = CreateThread(
|
||||
&sa,
|
||||
0,
|
||||
ThreadProc1,
|
||||
&s,
|
||||
0,
|
||||
&threadId);
|
||||
}
|
||||
|
||||
{
|
||||
DWORD threadId;
|
||||
HANDLE threadHandle = CreateRemoteThread(
|
||||
nullptr,
|
||||
&sa,
|
||||
0,
|
||||
ThreadProc2,
|
||||
&s,
|
||||
0,
|
||||
&threadId);
|
||||
}
|
||||
|
||||
{
|
||||
DWORD threadId;
|
||||
PROC_THREAD_ATTRIBUTE_LIST attrList;
|
||||
HANDLE threadHandle = CreateRemoteThreadEx(
|
||||
nullptr,
|
||||
&sa,
|
||||
0,
|
||||
ThreadProc3,
|
||||
&s,
|
||||
0,
|
||||
&attrList,
|
||||
&threadId);
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,6 @@ inputs:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
default: false
|
||||
dynamic-join-order-mode:
|
||||
description: Value of the --dynamic-join-order-mode flag to pass to the codeql test command
|
||||
required: false
|
||||
default: "none"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
@@ -67,15 +63,3 @@ runs:
|
||||
with:
|
||||
name: qhelp-markdown
|
||||
path: go/qhelp-out/**/*.md
|
||||
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: go-qltest
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cd go
|
||||
make test cache="${{ steps.query-cache.outputs.cache-dir }}" rtjo=${{ inputs.dynamic-join-order-mode }}
|
||||
|
||||
50
rust/ast-generator/src/field_info.rs
Normal file
50
rust/ast-generator/src/field_info.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum FieldType {
|
||||
String,
|
||||
Predicate,
|
||||
Optional(String),
|
||||
Body(String),
|
||||
List(String),
|
||||
}
|
||||
|
||||
pub struct FieldInfo {
|
||||
pub name: String,
|
||||
pub ty: FieldType,
|
||||
}
|
||||
|
||||
impl FieldInfo {
|
||||
pub fn optional(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Optional(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Body(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::String,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn predicate(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::List(ty.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,10 @@ use std::{fs, path::PathBuf};
|
||||
|
||||
pub mod codegen;
|
||||
mod flags;
|
||||
mod field_info;
|
||||
|
||||
use crate::codegen::grammar::ast_src::{AstEnumSrc, Cardinality};
|
||||
use crate::field_info::{FieldInfo, FieldType};
|
||||
use codegen::grammar::ast_src::{AstNodeSrc, AstSrc, Field};
|
||||
use itertools::Itertools;
|
||||
use serde::Serialize;
|
||||
@@ -10,11 +13,6 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::env;
|
||||
use ungrammar::Grammar;
|
||||
|
||||
fn project_root() -> PathBuf {
|
||||
let dir = env::var("CARGO_MANIFEST_DIR").unwrap().to_owned();
|
||||
PathBuf::from(dir).parent().unwrap().to_owned()
|
||||
}
|
||||
|
||||
fn class_name(type_name: &str) -> String {
|
||||
match type_name {
|
||||
"BinExpr" => "BinaryExpr".to_owned(),
|
||||
@@ -78,6 +76,128 @@ fn has_special_emission(type_name: &str) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
fn should_enum_be_skipped(name: &str) -> bool {
|
||||
name == "VariantDef" // remove the VariantDef enum, there is no use for it at the moment
|
||||
|
||||
}
|
||||
|
||||
fn should_node_be_skipped(name: &str) -> bool {
|
||||
name == "TypeAnchor" // we flatten TypeAnchor into PathSegment in the extractor
|
||||
}
|
||||
|
||||
fn should_node_be_skipped_in_extractor(name: &str) -> bool {
|
||||
name == "Adt" // no fields have `Adt` type, so we don't need extraction for it
|
||||
}
|
||||
|
||||
fn should_field_be_skipped(node_name: &str, field_name: &str) -> bool {
|
||||
matches!(
|
||||
(node_name, field_name),
|
||||
("ArrayExpr", "expr") // The ArrayExpr type also has an 'exprs' field
|
||||
| ("PathSegment", "type_anchor") // we flatten TypeAnchor into PathSegment in the extractor
|
||||
| ("Param", "pat") | ("MacroCall", "token_tree") // handled manually to use `body`
|
||||
)
|
||||
}
|
||||
|
||||
fn get_additional_fields(node_name: &str) -> Vec<FieldInfo> {
|
||||
match node_name {
|
||||
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo::string("text")],
|
||||
"Abi" => vec![FieldInfo::string("abi_string")],
|
||||
"Literal" => vec![FieldInfo::string("text_value")],
|
||||
"PrefixExpr" => vec![FieldInfo::string("operator_name")],
|
||||
"BinExpr" => vec![
|
||||
FieldInfo::optional("lhs", "Expr"),
|
||||
FieldInfo::optional("rhs", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IfExpr" => vec![
|
||||
FieldInfo::optional("then_branch", "BlockExpr"),
|
||||
FieldInfo::optional("else_branch", "ElseBranch"),
|
||||
FieldInfo::optional("condition", "Expr"),
|
||||
],
|
||||
"RangeExpr" => vec![
|
||||
FieldInfo::optional("start", "Expr"),
|
||||
FieldInfo::optional("end", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"RangePat" => vec![
|
||||
FieldInfo::optional("start", "Pat"),
|
||||
FieldInfo::optional("end", "Pat"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IndexExpr" => vec![
|
||||
FieldInfo::optional("index", "Expr"),
|
||||
FieldInfo::optional("base", "Expr"),
|
||||
],
|
||||
"Impl" => vec![
|
||||
FieldInfo::optional("trait_", "Type"),
|
||||
FieldInfo::optional("self_ty", "Type"),
|
||||
],
|
||||
"ForExpr" => vec![FieldInfo::optional("iterable", "Expr")],
|
||||
"WhileExpr" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MatchGuard" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MacroDef" => vec![
|
||||
FieldInfo::body("args", "TokenTree"),
|
||||
FieldInfo::body("body", "TokenTree"),
|
||||
],
|
||||
"MacroCall" => vec![FieldInfo::body("token_tree", "TokenTree")],
|
||||
"FormatArgsExpr" => vec![FieldInfo::list("args", "FormatArgsArg")],
|
||||
"ArgList" => vec![FieldInfo::list("args", "Expr")],
|
||||
"Fn" => vec![FieldInfo::body("body", "BlockExpr")],
|
||||
"Const" => vec![FieldInfo::body("body", "Expr")],
|
||||
"Static" => vec![FieldInfo::body("body", "Expr")],
|
||||
"Param" => vec![FieldInfo::body("pat", "Pat")],
|
||||
"ClosureExpr" => vec![FieldInfo::optional("body", "Expr")],
|
||||
"ArrayExpr" => vec![FieldInfo::predicate("is_semicolon")],
|
||||
"SelfParam" => vec![FieldInfo::predicate("is_amp")],
|
||||
"UseTree" => vec![FieldInfo::predicate("is_star")],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn get_trait_fields(trait_name: &str) -> Vec<FieldInfo> {
|
||||
match trait_name {
|
||||
"HasAttrs" => vec![FieldInfo::list("attrs", "Attr")],
|
||||
"HasName" => vec![FieldInfo::optional("name", "Name")],
|
||||
"HasVisibility" => vec![FieldInfo::optional("visibility", "Visibility")],
|
||||
"HasGenericParams" => vec![
|
||||
FieldInfo::optional("generic_param_list", "GenericParamList"),
|
||||
FieldInfo::optional("where_clause", "WhereClause"),
|
||||
],
|
||||
"HasGenericArgs" => vec![FieldInfo::optional("generic_arg_list", "GenericArgList")],
|
||||
"HasTypeBounds" => vec![FieldInfo::optional("type_bound_list", "TypeBoundList")],
|
||||
"HasModuleItem" => vec![FieldInfo::list("items", "Item")],
|
||||
"HasLoopBody" =>
|
||||
vec![FieldInfo::optional("label", "Label"),
|
||||
FieldInfo::optional("loop_body", "BlockExpr")],
|
||||
"HasArgList" => vec![FieldInfo::optional("arg_list", "ArgList")],
|
||||
"HasDocComments" => vec![],
|
||||
_ => panic!("Unknown trait {}", trait_name),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_predicate_be_extracted(name: &str) -> bool {
|
||||
matches!(
|
||||
name,
|
||||
"async"
|
||||
| "auto"
|
||||
| "const"
|
||||
| "default"
|
||||
| "gen"
|
||||
| "move"
|
||||
| "mut"
|
||||
| "raw"
|
||||
| "ref"
|
||||
| "static"
|
||||
| "try"
|
||||
| "unsafe"
|
||||
)
|
||||
}
|
||||
|
||||
fn project_root() -> PathBuf {
|
||||
let dir = env::var("CARGO_MANIFEST_DIR").unwrap().to_owned();
|
||||
PathBuf::from(dir).parent().unwrap().to_owned()
|
||||
}
|
||||
|
||||
fn to_lower_snake_case(s: &str) -> String {
|
||||
let mut buf = String::with_capacity(s.len());
|
||||
let mut prev = false;
|
||||
@@ -192,121 +312,11 @@ fn write_schema(
|
||||
Ok(fix_blank_lines(&res))
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum FieldType {
|
||||
String,
|
||||
Predicate,
|
||||
Optional(String),
|
||||
Body(String),
|
||||
List(String),
|
||||
}
|
||||
|
||||
struct FieldInfo {
|
||||
name: String,
|
||||
ty: FieldType,
|
||||
}
|
||||
|
||||
impl FieldInfo {
|
||||
pub fn optional(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Optional(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Body(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::String,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn predicate(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::List(ty.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_additional_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
match node.name.as_str() {
|
||||
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo::string("text")],
|
||||
"Abi" => vec![FieldInfo::string("abi_string")],
|
||||
"Literal" => vec![FieldInfo::string("text_value")],
|
||||
"PrefixExpr" => vec![FieldInfo::string("operator_name")],
|
||||
"BinExpr" => vec![
|
||||
FieldInfo::optional("lhs", "Expr"),
|
||||
FieldInfo::optional("rhs", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IfExpr" => vec![
|
||||
FieldInfo::optional("then_branch", "BlockExpr"),
|
||||
FieldInfo::optional("else_branch", "ElseBranch"),
|
||||
FieldInfo::optional("condition", "Expr"),
|
||||
],
|
||||
"RangeExpr" => vec![
|
||||
FieldInfo::optional("start", "Expr"),
|
||||
FieldInfo::optional("end", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"RangePat" => vec![
|
||||
FieldInfo::optional("start", "Pat"),
|
||||
FieldInfo::optional("end", "Pat"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IndexExpr" => vec![
|
||||
FieldInfo::optional("index", "Expr"),
|
||||
FieldInfo::optional("base", "Expr"),
|
||||
],
|
||||
"Impl" => vec![
|
||||
FieldInfo::optional("trait_", "Type"),
|
||||
FieldInfo::optional("self_ty", "Type"),
|
||||
],
|
||||
"ForExpr" => vec![FieldInfo::optional("iterable", "Expr")],
|
||||
"WhileExpr" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MatchGuard" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MacroDef" => vec![
|
||||
FieldInfo::body("args", "TokenTree"),
|
||||
FieldInfo::body("body", "TokenTree"),
|
||||
],
|
||||
"MacroCall" => vec![FieldInfo::body("token_tree", "TokenTree")],
|
||||
"FormatArgsExpr" => vec![FieldInfo::list("args", "FormatArgsArg")],
|
||||
"ArgList" => vec![FieldInfo::list("args", "Expr")],
|
||||
"Fn" => vec![FieldInfo::body("body", "BlockExpr")],
|
||||
"Const" => vec![FieldInfo::body("body", "Expr")],
|
||||
"Static" => vec![FieldInfo::body("body", "Expr")],
|
||||
"Param" => vec![FieldInfo::body("pat", "Pat")],
|
||||
"ClosureExpr" => vec![FieldInfo::optional("body", "Expr")],
|
||||
"ArrayExpr" => vec![FieldInfo::predicate("is_semicolon")],
|
||||
"SelfParam" => vec![FieldInfo::predicate("is_amp")],
|
||||
"UseTree" => vec![FieldInfo::predicate("is_star")],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
let mut result = Vec::new();
|
||||
let predicates = [
|
||||
"async", "auto", "const", "default", "gen", "move", "mut", "raw", "ref", "static", "try",
|
||||
"unsafe",
|
||||
];
|
||||
for field in &node.fields {
|
||||
if let Field::Token(name) = field {
|
||||
if predicates.contains(&name.as_str()) {
|
||||
if should_predicate_be_extracted(&name) {
|
||||
result.push(FieldInfo {
|
||||
name: format!("is_{name}"),
|
||||
ty: FieldType::Predicate,
|
||||
@@ -315,17 +325,11 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
}
|
||||
}
|
||||
|
||||
result.extend(get_additional_fields(node));
|
||||
result.extend(get_additional_fields(&node.name));
|
||||
|
||||
for field in &node.fields {
|
||||
let name = field.method_name();
|
||||
match (node.name.as_str(), name.as_str()) {
|
||||
("ArrayExpr", "expr") // The ArrayExpr type also has an 'exprs' field
|
||||
| ("PathSegment", "type_anchor") // we flatten TypeAnchor into PathSegment in the extractor
|
||||
| ("Param", "pat") | ("MacroCall", "token_tree") // handled manually to use `body`
|
||||
=> continue,
|
||||
_ => {}
|
||||
}
|
||||
if should_field_be_skipped(&node.name, &name) { continue; }
|
||||
let ty = match field {
|
||||
Field::Token(_) => continue,
|
||||
Field::Node {
|
||||
@@ -338,31 +342,7 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
result.push(FieldInfo { name, ty });
|
||||
}
|
||||
for trait_ in &node.traits {
|
||||
match trait_.as_str() {
|
||||
"HasAttrs" => result.push(FieldInfo::list("attrs", "Attr")),
|
||||
"HasName" => result.push(FieldInfo::optional("name", "Name")),
|
||||
"HasVisibility" => result.push(FieldInfo::optional("visibility", "Visibility")),
|
||||
"HasGenericParams" => {
|
||||
result.push(FieldInfo::optional(
|
||||
"generic_param_list",
|
||||
"GenericParamList",
|
||||
));
|
||||
result.push(FieldInfo::optional("where_clause", "WhereClause"))
|
||||
}
|
||||
"HasGenericArgs" => {
|
||||
result.push(FieldInfo::optional("generic_arg_list", "GenericArgList"))
|
||||
}
|
||||
"HasTypeBounds" => result.push(FieldInfo::optional("type_bound_list", "TypeBoundList")),
|
||||
"HasModuleItem" => result.push(FieldInfo::list("items", "Item")),
|
||||
"HasLoopBody" => {
|
||||
result.push(FieldInfo::optional("label", "Label"));
|
||||
result.push(FieldInfo::optional("loop_body", "BlockExpr"))
|
||||
}
|
||||
"HasArgList" => result.push(FieldInfo::optional("arg_list", "ArgList")),
|
||||
"HasDocComments" => {}
|
||||
|
||||
_ => panic!("Unknown trait {}", trait_),
|
||||
};
|
||||
result.extend(get_trait_fields(&trait_));
|
||||
}
|
||||
result.sort_by(|x, y| x.name.cmp(&y.name));
|
||||
result
|
||||
@@ -412,12 +392,8 @@ struct ExtractorInfo {
|
||||
nodes: Vec<ExtractorNodeInfo>,
|
||||
}
|
||||
|
||||
fn enum_to_extractor_info(node: &AstEnumSrc) -> Option<ExtractorEnumInfo> {
|
||||
if node.name == "Adt" {
|
||||
// no fields have `Adt` type, so we don't need extraction for it
|
||||
return None;
|
||||
}
|
||||
Some(ExtractorEnumInfo {
|
||||
fn enum_to_extractor_info(node: &AstEnumSrc) -> ExtractorEnumInfo {
|
||||
ExtractorEnumInfo {
|
||||
name: class_name(&node.name),
|
||||
snake_case_name: to_lower_snake_case(&node.name),
|
||||
ast_name: node.name.clone(),
|
||||
@@ -435,7 +411,7 @@ fn enum_to_extractor_info(node: &AstEnumSrc) -> Option<ExtractorEnumInfo> {
|
||||
})
|
||||
.collect(),
|
||||
has_special_emission: has_special_emission(&node.name),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn field_info_to_extractor_info(name: &str, field: &FieldInfo) -> ExtractorNodeFieldInfo {
|
||||
@@ -498,7 +474,8 @@ fn write_extractor(grammar: &AstSrc, mustache_ctx: &mustache::Context) -> mustac
|
||||
enums: grammar
|
||||
.enums
|
||||
.iter()
|
||||
.filter_map(enum_to_extractor_info)
|
||||
.filter(|e| !should_node_be_skipped_in_extractor(&e.name))
|
||||
.map(enum_to_extractor_info)
|
||||
.collect(),
|
||||
nodes: grammar.nodes.iter().map(node_to_extractor_info).collect(),
|
||||
};
|
||||
@@ -514,11 +491,8 @@ fn main() -> anyhow::Result<()> {
|
||||
.parse()
|
||||
.expect("Failed to parse grammar");
|
||||
let mut grammar = codegen::grammar::lower(&grammar);
|
||||
// remove the VariantDef enum, there is no use for it at the moment
|
||||
grammar.enums.retain(|e| e.name != "VariantDef");
|
||||
|
||||
// we flatten TypeAnchor into PathSegment in the extractor
|
||||
grammar.nodes.retain(|x| x.name != "TypeAnchor");
|
||||
grammar.enums.retain(|e| !should_enum_be_skipped(&e.name));
|
||||
grammar.nodes.retain(|x| !should_node_be_skipped(&x.name));
|
||||
|
||||
let mut super_types: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
|
||||
for node in &grammar.enums {
|
||||
|
||||
@@ -71,6 +71,7 @@ pub struct Config {
|
||||
pub proc_macro_server: Option<PathBuf>,
|
||||
pub skip_path_resolution: bool,
|
||||
pub extract_dependencies_as_source: bool,
|
||||
pub force_library_mode: bool, // for testing purposes
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
||||
@@ -293,6 +293,11 @@ fn main() -> anyhow::Result<()> {
|
||||
} else {
|
||||
(SourceKind::Library, ResolvePaths::No)
|
||||
};
|
||||
let (source_mode, source_resolve_paths) = if cfg.force_library_mode {
|
||||
(library_mode, library_resolve_paths)
|
||||
} else {
|
||||
(SourceKind::Source, resolve_paths)
|
||||
};
|
||||
let mut processed_files: HashSet<PathBuf, RandomState> =
|
||||
HashSet::from_iter(files.iter().cloned());
|
||||
for (manifest, files) in map.values().filter(|(_, files)| !files.is_empty()) {
|
||||
@@ -311,12 +316,10 @@ fn main() -> anyhow::Result<()> {
|
||||
file,
|
||||
&semantics,
|
||||
vfs,
|
||||
resolve_paths,
|
||||
SourceKind::Source,
|
||||
source_resolve_paths,
|
||||
source_mode,
|
||||
),
|
||||
Err(reason) => {
|
||||
extractor.extract_without_semantics(file, SourceKind::Source, &reason)
|
||||
}
|
||||
Err(reason) => extractor.extract_without_semantics(file, source_mode, &reason),
|
||||
};
|
||||
}
|
||||
for (file_id, file) in vfs.iter() {
|
||||
|
||||
@@ -19,7 +19,7 @@ fn dump_lib() -> anyhow::Result<()> {
|
||||
.iter()
|
||||
.map(|p| p.file_stem().expect("results of glob must have a name"))
|
||||
.filter(|&p| !["main", "lib", "proc_macro"].map(OsStr::new).contains(&p))
|
||||
.map(|p| format!("mod {};", p.to_string_lossy()))
|
||||
.map(|p| format!("pub mod {};", p.to_string_lossy()))
|
||||
.join("\n");
|
||||
fs::write("lib.rs", lib).context("writing lib.rs")
|
||||
}
|
||||
|
||||
@@ -24,33 +24,31 @@ use ra_ap_syntax::{
|
||||
|
||||
impl Emission<ast::Item> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::Item) -> Option<Label<generated::Item>> {
|
||||
self.prepare_item_expansion(node).map(Into::into)
|
||||
self.item_pre_emit(node).map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::Item, label: Label<generated::Item>) {
|
||||
self.emit_item_expansion(node, label);
|
||||
self.item_post_emit(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::AssocItem> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::AssocItem) -> Option<Label<generated::AssocItem>> {
|
||||
self.prepare_item_expansion(&node.clone().into())
|
||||
.map(Into::into)
|
||||
self.item_pre_emit(&node.clone().into()).map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::AssocItem, label: Label<generated::AssocItem>) {
|
||||
self.emit_item_expansion(&node.clone().into(), label.into());
|
||||
self.item_post_emit(&node.clone().into(), label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::ExternItem> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::ExternItem) -> Option<Label<generated::ExternItem>> {
|
||||
self.prepare_item_expansion(&node.clone().into())
|
||||
.map(Into::into)
|
||||
self.item_pre_emit(&node.clone().into()).map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::ExternItem, label: Label<generated::ExternItem>) {
|
||||
self.emit_item_expansion(&node.clone().into(), label.into());
|
||||
self.item_post_emit(&node.clone().into(), label.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,35 +847,6 @@ impl<'a> Translator<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_item_expansion(
|
||||
&mut self,
|
||||
node: &ast::Item,
|
||||
) -> Option<Label<generated::MacroCall>> {
|
||||
if self.source_kind == SourceKind::Library {
|
||||
// if the item expands via an attribute macro, we want to only emit the expansion
|
||||
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
|
||||
// we wrap it in a dummy MacroCall to get a single Item label that can replace
|
||||
// the original Item
|
||||
let label = self.trap.emit(generated::MacroCall {
|
||||
id: TrapId::Star,
|
||||
attrs: vec![],
|
||||
path: None,
|
||||
token_tree: None,
|
||||
});
|
||||
generated::MacroCall::emit_macro_call_expansion(
|
||||
label,
|
||||
expanded.into(),
|
||||
&mut self.trap.writer,
|
||||
);
|
||||
return Some(label);
|
||||
}
|
||||
}
|
||||
if self.is_attribute_macro_target(node) {
|
||||
self.macro_context_depth += 1;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn process_item_macro_expansion(
|
||||
&mut self,
|
||||
node: &impl ast::AstNode,
|
||||
@@ -915,10 +884,6 @@ impl<'a> Translator<'a> {
|
||||
&mut self,
|
||||
node: &ast::Item,
|
||||
) -> Option<Label<generated::MacroItems>> {
|
||||
if !self.is_attribute_macro_target(node) {
|
||||
return None;
|
||||
}
|
||||
self.macro_context_depth -= 1;
|
||||
if self.macro_context_depth > 0 {
|
||||
// only expand the outermost attribute macro
|
||||
return None;
|
||||
@@ -927,7 +892,49 @@ impl<'a> Translator<'a> {
|
||||
self.process_item_macro_expansion(node, expansion.map(|x| x.value))
|
||||
}
|
||||
|
||||
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
|
||||
pub(crate) fn item_pre_emit(
|
||||
&mut self,
|
||||
node: &ast::Item,
|
||||
) -> Option<Label<generated::MacroCall>> {
|
||||
if !self.is_attribute_macro_target(node) {
|
||||
return None;
|
||||
}
|
||||
if self.source_kind == SourceKind::Library {
|
||||
// if the item expands via an attribute macro, we want to only emit the expansion
|
||||
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
|
||||
// we wrap it in a dummy MacroCall to get a single Item label that can replace
|
||||
// the original Item
|
||||
let label = self.trap.emit(generated::MacroCall {
|
||||
id: TrapId::Star,
|
||||
attrs: vec![],
|
||||
path: None,
|
||||
token_tree: None,
|
||||
});
|
||||
generated::Item::emit_attribute_macro_expansion(
|
||||
label.into(),
|
||||
expanded,
|
||||
&mut self.trap.writer,
|
||||
);
|
||||
self.emit_location(label, node);
|
||||
return Some(label);
|
||||
}
|
||||
}
|
||||
self.macro_context_depth += 1;
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn item_post_emit(&mut self, node: &ast::Item, label: Label<generated::Item>) {
|
||||
if !self.is_attribute_macro_target(node) {
|
||||
return;
|
||||
}
|
||||
// see `item_pre_emit`:
|
||||
// if self.is_attribute_macro_target(node), then we either exited early with `Some(label)`
|
||||
// and are not here, or we did self.macro_context_depth += 1
|
||||
assert!(
|
||||
self.macro_context_depth > 0,
|
||||
"macro_context_depth should be > 0 for an attribute macro target"
|
||||
);
|
||||
self.macro_context_depth -= 1;
|
||||
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
|
||||
generated::Item::emit_attribute_macro_expansion(label, expanded, &mut self.trap.writer);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class MacroCall extends Generated::MacroCall {
|
||||
override string toStringImpl() { result = this.getPath().toAbbreviatedString() + "!..." }
|
||||
override string toStringImpl() {
|
||||
if this.hasPath() then result = this.getPath().toAbbreviatedString() + "!..." else result = ""
|
||||
}
|
||||
|
||||
/** Gets an AST node whose location is inside the token tree belonging to this macro call. */
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -6,7 +6,7 @@ predicate toBeTested(Element e) {
|
||||
(
|
||||
not e instanceof Locatable
|
||||
or
|
||||
e.(Locatable).fromSource()
|
||||
exists(e.(Locatable).getFile().getRelativePath())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ canonicalPath
|
||||
| anonymous.rs:3:1:32:1 | fn canonicals | test::anonymous::canonicals |
|
||||
| anonymous.rs:34:1:36:1 | fn other | test::anonymous::other |
|
||||
| {EXTERNAL LOCATION} | fn trim | <core::str>::trim |
|
||||
| lib.rs:1:1:1:14 | mod anonymous | test::anonymous |
|
||||
| lib.rs:2:1:2:12 | mod regular | test::regular |
|
||||
| lib.rs:1:1:1:18 | mod anonymous | test::anonymous |
|
||||
| lib.rs:2:1:2:16 | mod regular | test::regular |
|
||||
| regular.rs:1:1:2:18 | struct Struct | test::regular::Struct |
|
||||
| regular.rs:2:12:2:17 | fn eq | <test::regular::Struct as core::cmp::PartialEq>::eq |
|
||||
| regular.rs:2:12:2:17 | impl ...::Eq for Struct::<...> { ... } | <test::regular::Struct as core::cmp::Eq> |
|
||||
@@ -42,8 +42,8 @@ canonicalPaths
|
||||
| anonymous.rs:26:5:31:5 | fn usage | None | None |
|
||||
| anonymous.rs:34:1:36:1 | fn other | repo::test | crate::anonymous::other |
|
||||
| anonymous.rs:35:5:35:23 | struct OtherStruct | None | None |
|
||||
| lib.rs:1:1:1:14 | mod anonymous | repo::test | crate::anonymous |
|
||||
| lib.rs:2:1:2:12 | mod regular | repo::test | crate::regular |
|
||||
| lib.rs:1:1:1:18 | mod anonymous | repo::test | crate::anonymous |
|
||||
| lib.rs:2:1:2:16 | mod regular | repo::test | crate::regular |
|
||||
| regular.rs:1:1:2:18 | struct Struct | repo::test | crate::regular::Struct |
|
||||
| regular.rs:2:12:2:17 | fn eq | repo::test | <crate::regular::Struct as crate::cmp::PartialEq>::eq |
|
||||
| regular.rs:2:12:2:17 | impl ...::Eq for Struct::<...> { ... } | None | None |
|
||||
|
||||
@@ -2,8 +2,8 @@ canonicalPath
|
||||
| anonymous.rs:6:1:35:1 | fn canonicals | test::anonymous::canonicals |
|
||||
| anonymous.rs:37:1:39:1 | fn other | test::anonymous::other |
|
||||
| {EXTERNAL LOCATION} | fn trim | <core::str>::trim |
|
||||
| lib.rs:1:1:1:14 | mod anonymous | test::anonymous |
|
||||
| lib.rs:2:1:2:12 | mod regular | test::regular |
|
||||
| lib.rs:1:1:1:18 | mod anonymous | test::anonymous |
|
||||
| lib.rs:2:1:2:16 | mod regular | test::regular |
|
||||
| regular.rs:4:1:5:18 | struct Struct | test::regular::Struct |
|
||||
| regular.rs:5:12:5:17 | fn eq | <test::regular::Struct as core::cmp::PartialEq>::eq |
|
||||
| regular.rs:5:12:5:17 | impl ...::Eq for Struct::<...> { ... } | <test::regular::Struct as core::cmp::Eq> |
|
||||
@@ -42,8 +42,8 @@ canonicalPaths
|
||||
| anonymous.rs:29:5:34:5 | fn usage | None | None |
|
||||
| anonymous.rs:37:1:39:1 | fn other | None | None |
|
||||
| anonymous.rs:38:5:38:23 | struct OtherStruct | None | None |
|
||||
| lib.rs:1:1:1:14 | mod anonymous | None | None |
|
||||
| lib.rs:2:1:2:12 | mod regular | None | None |
|
||||
| lib.rs:1:1:1:18 | mod anonymous | None | None |
|
||||
| lib.rs:2:1:2:16 | mod regular | None | None |
|
||||
| regular.rs:4:1:5:18 | struct Struct | None | None |
|
||||
| regular.rs:5:12:5:17 | fn eq | None | None |
|
||||
| regular.rs:5:12:5:17 | impl ...::Eq for Struct::<...> { ... } | None | None |
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
instances
|
||||
| gen_module.rs:3:1:4:8 | mod foo |
|
||||
| gen_module.rs:5:1:7:1 | mod bar |
|
||||
| lib.rs:1:1:1:15 | mod gen_module |
|
||||
| lib.rs:1:1:1:19 | mod gen_module |
|
||||
getExtendedCanonicalPath
|
||||
| gen_module.rs:3:1:4:8 | mod foo | crate::gen_module::foo |
|
||||
| gen_module.rs:5:1:7:1 | mod bar | crate::gen_module::bar |
|
||||
| lib.rs:1:1:1:15 | mod gen_module | crate::gen_module |
|
||||
| lib.rs:1:1:1:19 | mod gen_module | crate::gen_module |
|
||||
getCrateOrigin
|
||||
| gen_module.rs:3:1:4:8 | mod foo | repo::test |
|
||||
| gen_module.rs:5:1:7:1 | mod bar | repo::test |
|
||||
| lib.rs:1:1:1:15 | mod gen_module | repo::test |
|
||||
| lib.rs:1:1:1:19 | mod gen_module | repo::test |
|
||||
getAttributeMacroExpansion
|
||||
getAttr
|
||||
getItemList
|
||||
@@ -17,5 +17,6 @@ getItemList
|
||||
getName
|
||||
| gen_module.rs:3:1:4:8 | mod foo | gen_module.rs:4:5:4:7 | foo |
|
||||
| gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:5:5:7 | bar |
|
||||
| lib.rs:1:1:1:15 | mod gen_module | lib.rs:1:5:1:14 | gen_module |
|
||||
| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:9:1:18 | gen_module |
|
||||
getVisibility
|
||||
| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:1:1:3 | Visibility |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
instances
|
||||
| gen_name.rs:3:4:3:12 | test_name |
|
||||
| gen_name.rs:7:9:7:11 | foo |
|
||||
| lib.rs:1:5:1:12 | gen_name |
|
||||
| lib.rs:1:9:1:16 | gen_name |
|
||||
getText
|
||||
| gen_name.rs:3:4:3:12 | test_name | test_name |
|
||||
| gen_name.rs:7:9:7:11 | foo | foo |
|
||||
| lib.rs:1:5:1:12 | gen_name | gen_name |
|
||||
| lib.rs:1:9:1:16 | gen_name | gen_name |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
instances
|
||||
| gen_source_file.rs:1:1:9:2 | SourceFile |
|
||||
| lib.rs:1:1:1:20 | SourceFile |
|
||||
| lib.rs:1:1:1:24 | SourceFile |
|
||||
getAttr
|
||||
getItem
|
||||
| gen_source_file.rs:1:1:9:2 | SourceFile | 0 | gen_source_file.rs:3:1:9:1 | fn test_source_file |
|
||||
| lib.rs:1:1:1:20 | SourceFile | 0 | lib.rs:1:1:1:20 | mod gen_source_file |
|
||||
| lib.rs:1:1:1:24 | SourceFile | 0 | lib.rs:1:1:1:24 | mod gen_source_file |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
instances
|
||||
| gen_visibility.rs:7:7:7:9 | Visibility |
|
||||
| lib.rs:1:1:1:3 | Visibility |
|
||||
getPath
|
||||
|
||||
@@ -146,8 +146,10 @@ lib.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [Module] mod call
|
||||
# 1| getName(): [Name] call
|
||||
# 1| getVisibility(): [Visibility] Visibility
|
||||
# 2| getItem(1): [Module] mod macro_expansion
|
||||
# 2| getName(): [Name] macro_expansion
|
||||
# 2| getVisibility(): [Visibility] Visibility
|
||||
macro_expansion.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [Use] use proc_macro::{...}
|
||||
|
||||
53
rust/ql/test/extractor-tests/macro-in-library/Cargo.lock
generated
Normal file
53
rust/ql/test/extractor-tests/macro-in-library/Cargo.lock
generated
Normal file
@@ -0,0 +1,53 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc_macro"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"proc_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
@@ -0,0 +1,63 @@
|
||||
lib.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [Module] mod macro_in_library
|
||||
# 1| getName(): [Name] macro_in_library
|
||||
# 1| getVisibility(): [Visibility] Visibility
|
||||
macro_in_library.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [MacroCall]
|
||||
# 2| getAttributeMacroExpansion(): [MacroItems] MacroItems
|
||||
# 2| getItem(0): [Function] fn foo
|
||||
# 2| getParamList(): [ParamList] ParamList
|
||||
# 2| getName(): [Name] foo
|
||||
# 2| getVisibility(): [Visibility] Visibility
|
||||
# 2| getItem(1): [Function] fn foo_new
|
||||
# 2| getParamList(): [ParamList] ParamList
|
||||
# 2| getName(): [Name] foo_new
|
||||
# 2| getVisibility(): [Visibility] Visibility
|
||||
# 4| getItem(1): [Function] fn bar
|
||||
# 4| getParamList(): [ParamList] ParamList
|
||||
# 4| getName(): [Name] bar
|
||||
# 4| getVisibility(): [Visibility] Visibility
|
||||
proc_macro.rs:
|
||||
# 1| [SourceFile] SourceFile
|
||||
# 1| getItem(0): [Use] use ...::TokenStream
|
||||
# 1| getUseTree(): [UseTree] ...::TokenStream
|
||||
# 1| getPath(): [Path] ...::TokenStream
|
||||
# 1| getQualifier(): [Path] proc_macro
|
||||
# 1| getSegment(): [PathSegment] proc_macro
|
||||
# 1| getIdentifier(): [NameRef] proc_macro
|
||||
# 1| getSegment(): [PathSegment] TokenStream
|
||||
# 1| getIdentifier(): [NameRef] TokenStream
|
||||
# 2| getItem(1): [Use] use ...::quote
|
||||
# 2| getUseTree(): [UseTree] ...::quote
|
||||
# 2| getPath(): [Path] ...::quote
|
||||
# 2| getQualifier(): [Path] quote
|
||||
# 2| getSegment(): [PathSegment] quote
|
||||
# 2| getIdentifier(): [NameRef] quote
|
||||
# 2| getSegment(): [PathSegment] quote
|
||||
# 2| getIdentifier(): [NameRef] quote
|
||||
# 4| getItem(2): [Function] fn add_one
|
||||
# 5| getParamList(): [ParamList] ParamList
|
||||
# 5| getParam(0): [Param] : TokenStream
|
||||
# 5| getTypeRepr(): [PathTypeRepr] TokenStream
|
||||
# 5| getPath(): [Path] TokenStream
|
||||
# 5| getSegment(): [PathSegment] TokenStream
|
||||
# 5| getIdentifier(): [NameRef] TokenStream
|
||||
# 5| getParam(1): [Param] : TokenStream
|
||||
# 5| getTypeRepr(): [PathTypeRepr] TokenStream
|
||||
# 5| getPath(): [Path] TokenStream
|
||||
# 5| getSegment(): [PathSegment] TokenStream
|
||||
# 5| getIdentifier(): [NameRef] TokenStream
|
||||
# 4| getAttr(0): [Attr] Attr
|
||||
# 4| getMeta(): [Meta] Meta
|
||||
# 4| getPath(): [Path] proc_macro_attribute
|
||||
# 4| getSegment(): [PathSegment] proc_macro_attribute
|
||||
# 4| getIdentifier(): [NameRef] proc_macro_attribute
|
||||
# 5| getName(): [Name] add_one
|
||||
# 5| getRetType(): [RetTypeRepr] RetTypeRepr
|
||||
# 5| getTypeRepr(): [PathTypeRepr] TokenStream
|
||||
# 5| getPath(): [Path] TokenStream
|
||||
# 5| getSegment(): [PathSegment] TokenStream
|
||||
# 5| getIdentifier(): [NameRef] TokenStream
|
||||
# 5| getVisibility(): [Visibility] Visibility
|
||||
@@ -0,0 +1 @@
|
||||
utils/PrintAst.ql
|
||||
@@ -0,0 +1,6 @@
|
||||
#[proc_macro::add_one]
|
||||
pub fn foo() {}
|
||||
|
||||
pub fn bar() {
|
||||
foo_new();
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
force_library_mode: true
|
||||
14
rust/ql/test/extractor-tests/macro-in-library/proc_macro.rs
Normal file
14
rust/ql/test/extractor-tests/macro-in-library/proc_macro.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn add_one(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse_macro_input!(item as syn::ItemFn);
|
||||
let mut new_ast = ast.clone();
|
||||
new_ast.sig.ident = syn::Ident::new(&format!("{}_new", ast.sig.ident), ast.sig.ident.span());
|
||||
quote! {
|
||||
#ast
|
||||
#new_ast
|
||||
}.into()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
macro_items
|
||||
| macro_in_library.rs:2:1:2:14 | MacroItems | 0 | macro_in_library.rs:2:1:2:14 | fn foo |
|
||||
| macro_in_library.rs:2:1:2:14 | MacroItems | 1 | macro_in_library.rs:2:1:2:14 | fn foo_new |
|
||||
warnings
|
||||
10
rust/ql/test/extractor-tests/macro-in-library/test.ql
Normal file
10
rust/ql/test/extractor-tests/macro-in-library/test.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import rust
|
||||
import codeql.rust.Diagnostics
|
||||
|
||||
query predicate macro_items(MacroItems c, int index, Item expanded) {
|
||||
exists(c.getFile().getRelativePath()) and
|
||||
not c.getLocation().getFile().getAbsolutePath().matches("%proc_macro.rs") and
|
||||
expanded = c.getItem(index)
|
||||
}
|
||||
|
||||
query predicate warnings(ExtractionWarning w) { any() }
|
||||
@@ -1,6 +1,7 @@
|
||||
| lib.rs:1:1:1:21 | SourceFile |
|
||||
| lib.rs:1:1:1:21 | mod utf8_identifiers |
|
||||
| lib.rs:1:5:1:20 | utf8_identifiers |
|
||||
| lib.rs:1:1:1:3 | Visibility |
|
||||
| lib.rs:1:1:1:25 | SourceFile |
|
||||
| lib.rs:1:1:1:25 | mod utf8_identifiers |
|
||||
| lib.rs:1:9:1:24 | utf8_identifiers |
|
||||
| utf8_identifiers.rs:1:1:4:6 | fn foo |
|
||||
| utf8_identifiers.rs:1:1:12:2 | SourceFile |
|
||||
| utf8_identifiers.rs:1:4:1:6 | foo |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mod
|
||||
| lib.rs:1:1:1:7 | mod my |
|
||||
| lib.rs:1:1:1:11 | mod my |
|
||||
| main.rs:1:1:1:7 | mod my |
|
||||
| main.rs:7:1:7:8 | mod my2 |
|
||||
| main.rs:13:1:37:1 | mod m1 |
|
||||
|
||||
Reference in New Issue
Block a user