feat: with json body

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-07-04 22:34:31 +02:00
parent c34df2ccaa
commit 20ea4b66b9
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
10 changed files with 3426 additions and 1037 deletions

20
corpus/assertions.txt Normal file
View File

@ -0,0 +1,20 @@
===
Assertion
===
GET https://somewhere.com
HTTP 200
[Asserts]
---
(source_file
(request_declaration
(request_literal)
(url))
(response
(scheme_literal)
(status_code_pattern))
(assert_declaration
(assert_literal)))

View File

@ -1,21 +1,22 @@
===
Comments
===
GET https://somewhere.com # some comment
GET https://somewhere.com # some comment
# comment
HTTP 200 # comment
HTTP 200
# comment
---
(source_file
(request_declaration
(request_literal)
(url))
(comment)
(comment)
(response
(scheme_literal)
(status_code_pattern))
(comment))
(request_literal)
(url))
(comment)
(comment)
(response
(scheme_literal)
(status_code_pattern))
(comment))

View File

@ -116,3 +116,27 @@ HTTP 302
(response
(scheme_literal)
(status_code_pattern)))
===
Request body json
===
POST https://somewhere.com?query=something
{
"some-name": "some-value"
}
HTTP 302
---
(source_file
(request_declaration
(request_literal)
(url))
(body
(json_request_declaration))
(response
(scheme_literal)
(status_code_pattern)))

View File

@ -1,9 +1,21 @@
const NL = token.immediate(/[\r\n]+/);
const PREC = {
comment: 1,
request: 2,
header: 3,
param: 4,
body: 5,
var: 6,
whitespace: 7,
new_line: 8,
}
module.exports = grammar({
name: "hurl",
extras: $ => [
$.comment,
/\s/
],
rules: {
@ -12,32 +24,48 @@ module.exports = grammar({
// statements
_statement: ($) =>
choice($._declaration_statement),
choice($._declaration_statement, NL),
_declaration_statement: ($) =>
_declaration_statement: ($) => seq(
choice(
$.request_declaration,
$.header_declaration,
alias($.http_response_declaration, $.response),
$.assert_declaration,
alias($.request_body_declaration, $.body),
),
prec.left(PREC.whitespace, optional($._whitespace)),
),
// declarations
request_declaration: ($) =>
seq($._literal, field("url", $.url)),
prec.left(PREC.request,
seq($._literal, $._whitespace, field("url", $.url)),
),
request_body_declaration: $ => choice(
$.json_request_declaration
),
json_request_declaration: $ => prec.left(PREC.body, seq(/\{/, optional(repeat(choice(/\n/))), repeat(seq($._line, NL)), /\}\n\n/)),
header_declaration: ($) =>
seq(
field("header_name", $.header_name),
":",
optional($._whitespace),
field("header_value", $.header_value)
),
http_response_declaration: $ => seq($.scheme_literal, $.status_code_pattern),
http_response_declaration: $ => seq($.scheme_literal, $._whitespace, $.status_code_pattern),
assert_declaration: $ => seq('[', $.assert_literal, ']'),
// literals
_literal: ($) => choice($.request_literal),
_literal: ($) => choice($.request_literal, $.assert_literal),
request_literal: (_$) =>
choice(
@ -58,18 +86,31 @@ module.exports = grammar({
"VIEW"
),
assert_literal: $ => choice(
"QueryStringParams",
"FormParams",
"MultipartFormData",
"Cookies",
"Captures",
"Asserts",
"Options",
),
scheme_literal: $ => "HTTP",
// patterns
comment: $ => token(prec(-10, /#.*/)),
//comment: _ => prec.left(PREC.comment, token(seq("#", /.*/, optional(NL)))),
//comment_raw: _ => token(seq("#", /.*/, optional(NL))),
comment: _ => prec.left(PREC.comment, token(seq("#", /.*/, NL))),
status_code_pattern: $ => /[\d]{3}/,
header_name: ($) => /[a-zA-Z-_0-9]+/,
header_value: ($) =>
/[a-zA-Z\-_0-9\/\\]+/,
url: ($) => /\S+/,
_line: _ => /[^\n]+/,
_whitespace: _ => repeat1(/[\t\v ]/),
},
});

12
package-lock.json generated
View File

@ -9,7 +9,8 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"nan": "^2.17.0"
"nan": "^2.17.0",
"tree-sitter-json": "^0.20.0"
},
"devDependencies": {
"prettier": "^2.8.8",
@ -45,6 +46,15 @@
"bin": {
"tree-sitter": "cli.js"
}
},
"node_modules/tree-sitter-json": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.20.0.tgz",
"integrity": "sha512-PteOLH+Tx6Bz4ZA/d40/DbkiSXXRM/gKahhHI8hQ1lWNfFvdknnz9k3Mz84ol5srRyLboJ8wp8GSkhZ6ht9EGQ==",
"hasInstallScript": true,
"dependencies": {
"nan": "^2.14.1"
}
}
}
}

View File

@ -12,7 +12,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"nan": "^2.17.0"
"nan": "^2.17.0",
"tree-sitter-json": "^0.20.0"
},
"devDependencies": {
"prettier": "^2.8.8",

1
queries/injections.scm Normal file
View File

@ -0,0 +1 @@
(json_request_declaration) @json

View File

@ -14,48 +14,162 @@
{
"type": "SYMBOL",
"name": "_declaration_statement"
},
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[\\r\\n]+"
}
}
]
},
"_declaration_statement": {
"type": "CHOICE",
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "request_declaration"
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "request_declaration"
},
{
"type": "SYMBOL",
"name": "header_declaration"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "http_response_declaration"
},
"named": true,
"value": "response"
},
{
"type": "SYMBOL",
"name": "assert_declaration"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "request_body_declaration"
},
"named": true,
"value": "body"
}
]
},
{
"type": "SYMBOL",
"name": "header_declaration"
},
{
"type": "ALIAS",
"type": "PREC_LEFT",
"value": 7,
"content": {
"type": "SYMBOL",
"name": "http_response_declaration"
},
"named": true,
"value": "response"
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_whitespace"
},
{
"type": "BLANK"
}
]
}
}
]
},
"request_declaration": {
"type": "SEQ",
"type": "PREC_LEFT",
"value": 2,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_literal"
},
{
"type": "SYMBOL",
"name": "_whitespace"
},
{
"type": "FIELD",
"name": "url",
"content": {
"type": "SYMBOL",
"name": "url"
}
}
]
}
},
"request_body_declaration": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_literal"
},
{
"type": "FIELD",
"name": "url",
"content": {
"type": "SYMBOL",
"name": "url"
}
"name": "json_request_declaration"
}
]
},
"json_request_declaration": {
"type": "PREC_LEFT",
"value": 5,
"content": {
"type": "SEQ",
"members": [
{
"type": "PATTERN",
"value": "\\{"
},
{
"type": "CHOICE",
"members": [
{
"type": "REPEAT",
"content": {
"type": "CHOICE",
"members": [
{
"type": "PATTERN",
"value": "\\n"
}
]
}
},
{
"type": "BLANK"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_line"
},
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[\\r\\n]+"
}
}
]
}
},
{
"type": "PATTERN",
"value": "\\}\\n\\n"
}
]
}
},
"header_declaration": {
"type": "SEQ",
"members": [
@ -71,6 +185,18 @@
"type": "STRING",
"value": ":"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_whitespace"
},
{
"type": "BLANK"
}
]
},
{
"type": "FIELD",
"name": "header_value",
@ -88,18 +214,43 @@
"type": "SYMBOL",
"name": "scheme_literal"
},
{
"type": "SYMBOL",
"name": "_whitespace"
},
{
"type": "SYMBOL",
"name": "status_code_pattern"
}
]
},
"assert_declaration": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "SYMBOL",
"name": "assert_literal"
},
{
"type": "STRING",
"value": "]"
}
]
},
"_literal": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "request_literal"
},
{
"type": "SYMBOL",
"name": "assert_literal"
}
]
},
@ -168,18 +319,67 @@
}
]
},
"assert_literal": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "QueryStringParams"
},
{
"type": "STRING",
"value": "FormParams"
},
{
"type": "STRING",
"value": "MultipartFormData"
},
{
"type": "STRING",
"value": "Cookies"
},
{
"type": "STRING",
"value": "Captures"
},
{
"type": "STRING",
"value": "Asserts"
},
{
"type": "STRING",
"value": "Options"
}
]
},
"scheme_literal": {
"type": "STRING",
"value": "HTTP"
},
"comment": {
"type": "TOKEN",
"type": "PREC_LEFT",
"value": 1,
"content": {
"type": "PREC",
"value": -10,
"type": "TOKEN",
"content": {
"type": "PATTERN",
"value": "#.*"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "#"
},
{
"type": "PATTERN",
"value": ".*"
},
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[\\r\\n]+"
}
}
]
}
}
},
@ -198,16 +398,23 @@
"url": {
"type": "PATTERN",
"value": "\\S+"
},
"_line": {
"type": "PATTERN",
"value": "[^\\n]+"
},
"_whitespace": {
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "[\\t\\v ]"
}
}
},
"extras": [
{
"type": "SYMBOL",
"name": "comment"
},
{
"type": "PATTERN",
"value": "\\s"
}
],
"conflicts": [],

View File

@ -1,4 +1,44 @@
[
{
"type": "assert_declaration",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "assert_literal",
"named": true
}
]
}
},
{
"type": "assert_literal",
"named": true,
"fields": {}
},
{
"type": "body",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "json_request_declaration",
"named": true
}
]
}
},
{
"type": "comment",
"named": true,
"fields": {}
},
{
"type": "header_declaration",
"named": true,
@ -25,6 +65,11 @@
}
}
},
{
"type": "json_request_declaration",
"named": true,
"fields": {}
},
{
"type": "request_declaration",
"named": true,
@ -44,6 +89,10 @@
"multiple": false,
"required": true,
"types": [
{
"type": "assert_literal",
"named": true
},
{
"type": "request_literal",
"named": true
@ -83,6 +132,14 @@
"multiple": true,
"required": false,
"types": [
{
"type": "assert_declaration",
"named": true
},
{
"type": "body",
"named": true
},
{
"type": "header_declaration",
"named": true
@ -102,14 +159,30 @@
"type": ":",
"named": false
},
{
"type": "Asserts",
"named": false
},
{
"type": "CONNECT",
"named": false
},
{
"type": "Captures",
"named": false
},
{
"type": "Cookies",
"named": false
},
{
"type": "DELETE",
"named": false
},
{
"type": "FormParams",
"named": false
},
{
"type": "GET",
"named": false
@ -122,10 +195,18 @@
"type": "LOCK",
"named": false
},
{
"type": "MultipartFormData",
"named": false
},
{
"type": "OPTIONS",
"named": false
},
{
"type": "Options",
"named": false
},
{
"type": "PATCH",
"named": false
@ -146,6 +227,10 @@
"type": "PUT",
"named": false
},
{
"type": "QueryStringParams",
"named": false
},
{
"type": "TRACE",
"named": false
@ -163,8 +248,12 @@
"named": false
},
{
"type": "comment",
"named": true
"type": "[",
"named": false
},
{
"type": "]",
"named": false
},
{
"type": "header_name",

File diff suppressed because it is too large Load Diff