feat: improve queries (#316)

* feat: improve queries

* chore: format files
pull/324/head
Amaan Qureshi 1 year ago committed by GitHub
parent 1be8ef7cdf
commit f45b072606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,6 +3,7 @@
A modern go neovim plugin based on treesitter, nvim-lsp and dap debugger. It is written in Lua and async as much as possible.
PR & Suggestions welcome.
The plugin covers most features required for a gopher.
- Perproject setup. Allows you setup plugin behavior per project based on project files(launch.json, .gonvim)
- Async jobs with libuv
- Syntax highlight & Texobject: Native treesitter support is faster and more accurate. All you need is a theme support treesitter, try
@ -58,8 +59,8 @@ use 'neovim/nvim-lspconfig'
use 'nvim-treesitter/nvim-treesitter'
```
### [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
{
"ray-x/go.nvim",
@ -77,12 +78,10 @@ use 'nvim-treesitter/nvim-treesitter'
}
```
The go.nvim load speed is fast and you can enable it by default
<img width="479" alt="image" src="https://user-images.githubusercontent.com/1681295/218074895-5182c791-8649-46ad-b18e-8eb1af8c0ffa.png">
Make sure the `$GOPATH/bin` path is added to your `$PATH` environment variable. To check this you can run
```bash
@ -117,7 +116,6 @@ To startup/setup the plugin
require('go').setup()
```
## Screenshots
### Add comments
@ -133,16 +131,17 @@ require('go').setup()
![gotest](https://user-images.githubusercontent.com/1681295/143160335-b8046ffa-82cd-4d84-af3e-3b0dbb4c609e.png)
Use:
```vim
:GoTermClose
```
To close the floating term.
### SQL/JSON Highlight injection
<img width="718" alt="image" src="https://user-images.githubusercontent.com/1681295/227125827-538c5f3f-298d-4ae1-8762-42dfb92e79f3.png">
## refactor gorename
gorename as an alternative to gopls rename as it supports rename across packages
@ -217,7 +216,6 @@ Note: auto fill struct also supported by gopls lsp-action
[GoFixPlurals Youtube video](https://www.youtube.com/watch?v=IP67Gkb5-qA)
```go
package foo
@ -262,7 +260,7 @@ If you run `GoFmt` and the configured binary (e.g. golines) was not installed, t
first run of `GoFmt` may fail. Recommended to run `GoInstallBinaries` to install all binaries before using the plugin.
| command | Description |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| GoInstallBinary go_binary_name | use `go install go_binary_url@latest` to install tool, if installed will skip |
| GoUpdateBinary go_binary_name | use `go install go_binary_url@latest` Will force re-install/update if already installed, otherwise same as GoInstallBinary |
| GoInstallBinaries | use `go install` to install all tools, skip the ones installed |
@ -271,7 +269,7 @@ first run of `GoFmt` may fail. Recommended to run `GoInstallBinaries` to install
## Build and test
| command | Description |
| --------------------------------------------- | ------------------------------------------------------------------------ |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| GoMake | async make, use with other commands |
| GoBuild args | go build args (-g: enable debug, %: expand to current file, %:h expand to current package) |
| GoGenerate | |
@ -301,9 +299,10 @@ first run of `GoFmt` may fail. Recommended to run `GoInstallBinaries` to install
| GoTermClose | `closes the floating term` |
Note:
1. if package_url not provided, will check current line is a valid package url or not, if it is valid, will
fetch current url
2. tags: if ``//+build tags`` exist it will be added automatically
2. tags: if `//+build tags` exist it will be added automatically
3. args: if multiple args is provided, you need toconcatenate it with '\ ', e.g. GoTest -args yourtags\ other_args
4. % will expand to current file path, e.g. GoBuild %
@ -335,7 +334,7 @@ Support table based unit test auto generate, parse current function/method name
GoTestXXX Arguments
| arguments | Description |
| ------------ | --------------------------------- |
| --------- | ------------- |
| -v | verbose mode |
| -c | compile |
| -C | coverprofile |
@ -383,7 +382,6 @@ If guihua not installed fallback to loclist
<img width="902" alt="image" src="https://user-images.githubusercontent.com/1681295/175231905-82df4e4b-a508-4bb8-b878-9f0029643005.png">
## Modifytags
Modify struct tags by [`gomodifytags`](https://github.com/fatih/gomodifytags) and treesitter
@ -404,12 +402,12 @@ nvim-lsp support goimport by default. The plugin provided a new formatter, golin
gofmt)
| command | Description |
| --------------------- | --------------------------- |
| --------------------- | ------------------------ |
| GoFmt {opts} | default: gofumpt |
| GoImport | default: goimport |
| GoImport package_path | gopls add_import package |
{opts} : ``-a`` format all buffers
{opts} : `-a` format all buffers
## GoImpl
@ -431,21 +429,23 @@ e.g:
```
:GoImpl f *File io.Reader
```
or simply put your cursor in a struct and do
```
:GoImpl io.Reader
```
or simply your cursor on a interface and specify a receiver type
```
:GoImpl MyType
```
## Debug
| command | Description |
| ---------------- | ------------------------------------------------ |
| ------------------ | ------------------------------------------------ |
| GoDebug | start debug session, Note 1 |
| GoDebug -h | show helps info |
| GoDebug -c | compile only |
@ -464,6 +464,7 @@ or simply your cursor on a interface and specify a receiver type
| BreakCondition | conditional break |
Notes:
1. Without any argument, will check if launch.json existed or not, if existed, using launch.json and popup input.
If launch.json not existed, will start debug session for current file, if current file is package main will run
main(), else will start debug package test
@ -491,7 +492,6 @@ go mock with mockgen is supported
-p package name default: mocks
-d destination directory, default: ./mocks
## Comments and Doc
Auto doc (to suppress golang-lint warning), generate comments by treesitter parsing result
@ -512,14 +512,15 @@ The code will be:
// GoLintComplaining struct no more complaint ;P
type GoLintComplaining struct{}
```
| command | Description |
| ---------------- | ------------------------------------------------------- |
| ------- | ----------- |
| GoCmt | Add comment |
## GoModTidy
| command | Description |
| ---------------- | ------------------------------------------------------- |
| ----------- | ------------------------------------- |
| GoModInit | run `go mod init` and restart gopls |
| GoModTidy | run `go mod tidy` and restart gopls |
| GoModVendor | run `go mod vendor` and restart gopls |
@ -602,7 +603,7 @@ If launch.json is valid, run `GoDebug` will launch from the launch.json configur
### Command
* GoToggleInlay
- GoToggleInlay
#### Note:
@ -614,32 +615,38 @@ Please use jsonls/null-ls check your launch.json is valid json file. Following s
Here is a sample [launch.json](https://github.com/ray-x/go.nvim/blob/master/playground/sampleApp/.vscode/launch.json)
### Json to Go struct
* ["x]GoJson2Struct!
- ["x]GoJson2Struct!
Visual select the json and run `GoJson2Struct youStructName`
-bang will put result to register `a`
if ["x] specified, will put get json from clipboard
### Load Env file
* GoEnv {filename}
- GoEnv {filename}
By default load .env file in current directory, if you want to load other file, use {filename} option
### Generate return value
* GoGenReturn
- GoGenReturn
create return value for current function
e.g. if we have
```go
func Foo() (int, error) {
return 1, nil
}
```
and in your code you cursor on Foo
```go
Foo()
```
will generate
```go
i, err := Foo()
if err != nil {
@ -647,35 +654,36 @@ if err != nil {
}
```
### Rename modules
* Gomvp
- Gomvp
Rename module name in under cursor
e.g.
Gomvp
Gomvp old_mod_name
Gomvp old_mod_name new_mod_name
### govulncheck
* GoVulnCheck {arguments}
Run govulncheck on current project
- GoVulnCheck {arguments}
Run govulncheck on current project
### goenum
* Goenum {arguments}
Run goenum on current project
- Goenum {arguments}
Run goenum on current project
### gonew
* GoNew {filename}
- GoNew {filename}
Create new go file. It will use template file. e.g. `GoNew ./pkg/string.go` will create string.go with template file
### ginkgo
* Ginkgo {args}
- Ginkgo {args}
| Arg | Description |
| --- | ----------- |
| --------- | ----------- |
| run | |
| watch | |
| build | |
@ -683,7 +691,6 @@ Create new go file. It will use template file. e.g. `GoNew ./pkg/string.go` will
| labels | |
| outline | |
### Debug Commands
| Command | Description |
@ -864,8 +871,8 @@ return {
null_ls_document_formatting_disable = true
}
```
This will override your global `go.nvim` setup
This will override your global `go.nvim` setup
## Text object
@ -969,6 +976,7 @@ My treesitter config:
```
## LuaSnip supports
go.nvim provides a better snippet support for go.
Please check [snippets for all languages](https://github.com/ray-x/go.nvim/blob/master/lua/snips/all.lua)
and [snippets for go](https://github.com/ray-x/go.nvim/blob/master/lua/snips/go.lua)
@ -988,7 +996,6 @@ For diagnostic issue, you can use the default setup. There are also quite a few
## Integrate with mason-lspconfig
```lua
require("mason").setup()
require("mason-lspconfig").setup()
@ -1017,11 +1024,14 @@ local cfg = require'go.lsp'.config() -- config() return the go.nvim gopls setup
require('lspconfig').gopls.setup(cfg)
```
## Integrate null-ls
### The plugin provides:
* `gotest` LSP diagnostic source for null-ls
* `golangci_lint` A async version of golangci-lint null-ls lint
* `gotest_action` LSP test code action for null-ls
- `gotest` LSP diagnostic source for null-ls
- `golangci_lint` A async version of golangci-lint null-ls lint
- `gotest_action` LSP test code action for null-ls
Gotest allow you run `go test <package>` when you save your go file and add diagnostics to nvim
@ -1048,13 +1058,11 @@ null_ls.setup({ sources = sources, debounce = 1000, default_timeout = 5000 })
null_ls.register(gotest)
```
You will see the failed tests flagged
![null-ls
go.nvim](https://user-images.githubusercontent.com/1681295/212526174-4fa98a63-c90a-4a54-9340-27de98ecf17c.jpg)
## Sample vimrc
The following vimrc will enable all features provided by go.nvim
@ -1095,11 +1103,10 @@ EOF
This will setup gopls with non default configure provided by go.nvim (Includes lspconfig default keymaps)
## Other plugins that you may like
* [goplay](https://github.com/jeniasaigak/goplay.nvim)
* [a different way to highlight coverage results](https://github.com/rafaelsq/nvim-goc.lua)
- [goplay](https://github.com/jeniasaigak/goplay.nvim)
- [a different way to highlight coverage results](https://github.com/rafaelsq/nvim-goc.lua)
## Q & A:

@ -1,131 +1,58 @@
;; extends
; inject sql into any const string with word query in the name
; e.g. const query = `SELECT * FROM users WHERE name = 'John'`;
(
(const_spec
name: (identifier) @_id
value: (expression_list (raw_string_literal) @injection.content))
(#match? @_id ".*[Q|q]uery.*")
(#set! injection.language "sql")
)
(short_var_declaration
left: (expression_list
(identifier) @_id (#match? @_id ".*[Q|q]uery.*"))
right: (expression_list
(raw_string_literal) @sql (#offset! @sql 0 1 0 -1))
)
; extends
; inject sql in single line strings
; e.g. db.GetContext(ctx, "SELECT * FROM users WHERE name = 'John'")
(call_expression
((call_expression
(selector_expression
field: (field_identifier) @_field (#any-of? @_field "Exec" "GetContext" "ExecContext" "SelectContext" "In" "RebindNamed" "Rebind" "QueryRowxContext" "NamedExec"))
field: (field_identifier) @_field)
(argument_list
(interpreted_string_literal) @sql)
(interpreted_string_literal) @sql))
(#any-of? @_field "Exec" "GetContext" "ExecContext" "SelectContext" "In"
"RebindNamed" "Rebind" "QueryRowxContext" "NamedExec")
(#offset! @sql 0 1 0 -1))
; ----------------------------------------------------------------
; Go code example with interpreted string literal
; query := fmt.Sprintf("UPDATE task SET %s = ? WHERE id = ?", field)
(short_var_declaration
left: (expression_list) @_left (#eq? @_left "query")
right: (expression_list
(call_expression
function: (selector_expression
operand: (identifier) @_operand (#eq? @_operand "fmt")
field: (field_identifier) @_field (#eq? @_field "Sprintf")
)
arguments: (argument_list
(interpreted_string_literal) @sql
)
)
)
)
; ----------------------------------------------------------------
; Go code example with interpreted string literal and type identifier
; var query string = fmt.Sprintf("SELECT * from kkk WHERE id = ?", bb)
(var_declaration
(var_spec
name: (identifier) @_name (#match? @_name "[Q|q]uery")
value: (expression_list
(call_expression
function: (selector_expression
operand: (identifier) @_operand (#eq? @_operand "fmt")
field: (field_identifier) @_field (#eq? @_field "Sprintf")
)
arguments: (argument_list
(interpreted_string_literal) @sql
)
)
)
)
)
; ----------------------------------------------------------------
; Go code example with interpreted string literal and type identifier:
; var query string = "SELECT * FROM books"
(var_declaration
(var_spec
name: (identifier) @_name (#match? @_name "[Q|q]uery")
value: (expression_list
(interpreted_string_literal) @sql
)
)
)
; ----------------------------------------------------------------
; a general query injection
(((
[(interpreted_string_literal)
(raw_string_literal)] @sql
(#match? @sql "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?"
))))
([
(interpreted_string_literal)
(raw_string_literal)
] @sql
(#match? @sql "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
(#offset! @sql 0 1 0 -1))
; ----------------------------------------------------------------
; fallback keyword and comment based injection
(
(raw_string_literal) @sql
(#contains? @sql "-- sql" "--sql" "ADD CONSTRAINT" "ALTER TABLE" "ALTER COLUMN" "DATABASE" "FOREIGN KEY" "GROUP BY" "HAVING" "CREEATE INDEX" "INSERT INTO" "NOT NULL" "PRIMARY KEY" "UPDATE SET" "TRUNCATE TABLE" "LEFT JOIN")
(#offset! @sql 0 1 0 -1)
)
(
(interpreted_string_literal) @sql
(#contains? @sql "-- sql" "--sql" "ADD CONSTRAINT" "ALTER TABLE" "ALTER COLUMN" "DATABASE" "FOREIGN KEY" "GROUP BY" "HAVING" "CREEATE INDEX" "INSERT INTO" "NOT NULL" "PRIMARY KEY" "UPDATE SET" "TRUNCATE TABLE" "LEFT JOIN")
(#offset! @sql 0 1 0 -1)
)
([
(interpreted_string_literal)
(raw_string_literal)
] @sql
(#contains? @sql "-- sql" "--sql" "ADD CONSTRAINT" "ALTER TABLE" "ALTER COLUMN"
"DATABASE" "FOREIGN KEY" "GROUP BY" "HAVING" "CREATE INDEX" "INSERT INTO"
"NOT NULL" "PRIMARY KEY" "UPDATE SET" "TRUNCATE TABLE" "LEFT JOIN")
(#offset! @sql 0 1 0 -1))
; should I use a more exhaustive list of keywords?
; "ADD" "ADD CONSTRAINT" "ALL" "ALTER" "AND" "ASC" "COLUMN" "CONSTRAINT" "CREATE" "DATABASE" "DELETE" "DESC" "DISTINCT" "DROP" "EXISTS" "FOREIGN KEY" "FROM" "JOIN" "GROUP BY" "HAVING" "IN" "INDEX" "INSERT INTO" "LIKE" "LIMIT" "NOT" "NOT NULL" "OR" "ORDER BY" "PRIMARY KEY" "SELECT" "SET" "TABLE" "TRUNCATE TABLE" "UNION" "UNIQUE" "UPDATE" "VALUES" "WHERE"
; json
(
(const_spec
name: (identifier) @_id
value: (expression_list (raw_string_literal) @json))
(#match? @_id ".*[J|j]son.*")
)
((const_spec
name: (identifier) @_const
value: (expression_list (raw_string_literal) @json))
(#lua-match? @_const ".*[J|j]son.*"))
; jsonStr := `{"foo": "bar"}`
(short_var_declaration
((short_var_declaration
left: (expression_list
(identifier) @_id (#match? @_id ".*[J|j]son.*"))
(identifier) @_var)
right: (expression_list
(raw_string_literal) @json (#offset! @json 0 1 0 -1))
)
(raw_string_literal) @json))
(#lua-match? @_var ".*[J|j]son.*")
(#offset! @json 0 1 0 -1))
((composite_literal
type: (type_identifier) @_type
@ -133,5 +60,5 @@
(keyed_element
(literal_element) @_key
(literal_element) @lua)))
(#eq? @_key "overrideScript")
(#eq? @_type "generatorTestCase"))
(#eq? @_type "generatorTestCase")
(#eq? @_key "overrideScript"))

@ -1,15 +1,15 @@
;; extends
; extends
(var_spec) @scope
(field_declaration
name: (field_identifier) @definition.field)
(method_spec
name: (field_identifier) @method.name
parameters:(parameter_list) @method.parameter_list
)@interface.method.declaration
parameters: (parameter_list) @method.parameter_list) @interface.method.declaration
(type_declaration
(type_spec
name: (type_identifier) @name
type: [(struct_type) (interface_type)] @type)) @start
(var_spec) @scope

Loading…
Cancel
Save