How to use ast-grep with GraphQL
ast-grep
is a code search + replace tool that uses the abstract syntax tree (AST). It has language support for TypeScript, Python, and others, but it doesn't support GraphQL out of the box. However, there is documentation for supporting other languages: Custom Language Support.
These are my notes using that Custom Language Support documentation along with the Multi-Language Documents documentation to set up GraphQL support for ast-grep
on macOS.
Prepare Tree-sitter Tool and Parser
Install tree-sitter CLI
brew install tree-sitter
(Alternatively,
npm install -g tree-sitter-cli
)Test tree-sitter is installed
tree-sitter --version
tree-sitter 0.23.0
Use a working directory
I'll use
/tmp
as my working directory, but a different directory can be usedcd /tmp
Get the tree-sitter GraphQL grammar
git clone https://github.com/bkegley/tree-sitter-graphql.git
(This is the repo used by the neovim tree-sitter library.)
Compile the Parser as a Dynamic Library
Compile the GraphQL parser as a dynamic library
cd tree-sitter-graphql export TREE_SITTER_LIBDIR=/tmp tree-sitter test
Note: I got the following error when I ran this. If anyone knows what is going on, please let me know.
Error in query file "formatter.scm" Caused by: Query error at 5:31. Impossible pattern: (input_object_type_definition (input_value_definition) @field_definition)
However, it still generated the
graphql.dylib
file in/tmp
. Note: according to ChatGPT,.dylib
is used on Mac,.so
is used on Linux, and.dll
is used on Windows.
Register Language in sgconfig.yml
Create a new ast-grep project
cd /tmp sg new
No sgconfig.yml found. Creating a new ast-grep project... > Where do you want to have your rules? rules > Do you want to create rule tests? No > Do you want to create folder for utility rules? No Your new ast-grep project has been created!
Edit
sgconfig.yml
to add GraphQL as a custom language/tmp/sgconfig.yml
:ruleDirs: - ./rules customLanguages: graphql: libraryPath: graphql.dylib extensions: [graphql] expandoChar: $
Use It!
Search for all
input
types in/path/to/my/schema.graphql
sg -p "input" -l graphql /path/to/my/schema.graphql
/path/to/my/schema.graphql 6│input AddOrUpdateResidualWorksheetInputType { 120│input AutoAssignStyleCodeInputType { 478│input BulkCreateVehicleReleaseInputType { 483│input BulkDeleteVehicleReleaseInputType { 487│input BulkEditVehicleReleaseInputType { 492│input BulkImportStyleFromCppInputType { 949│input CloneModelInputType { 958│input CloneModelStyleInputType { 973│input CloneStyleInputType { 1749│input CppConfigurationInputType {
Search for all
DateTime
input fields (but not output fields) in/path/to/my/schema.graphql
. Note: thetree-sitter-graphql
grammer.js file contains differentkind
s that can be used for filtering.sg scan --inline-rules ' id: datetimeinputs language: graphql rule: regex: "DateTime" kind: input_value_definition ' /path/to/my/schema.graphql
help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:2356:3 │ 2356 │ configurationLastUpdatedAt: DateTime │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:8331:69 │ 8331 │ previousStyleSnapshot(styleSnapshotRowId: Guid, styleRowId: Long, versionDate: DateTime): StyleSnapshotTypeOrOperationErrorType │ ^^^^^^^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:8794:16 │ 8794 │ whatsChanged(date: DateTime!, flags: [WhatsChangedFilterFlagsEnumType], includeCppOrEmbargoedData: CppEmbargoedDataFilterEnumType): WhatsChangedType │ ^^^^^^^^^^^^^^^ help[datetimeinputs]: ┌─ /path/to/my/schema.graphql:11536:3 │ 11536 │ configurationLastUpdatedAt: DateTime │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^