go-parano

command module
v0.0.0-...-3c35577 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 4, 2023 License: MIT Imports: 7 Imported by: 0

README

go-parano

Experimental Go static analysis and robustness checker tool.

go-parano contains several features (see below), each feature checks a different thing. go-parano scans the source code (argument -dir or -pkg), including specific keywords in comments, and alerts (and returns exit code 2) if something is wrong.

Tested only on Linux, but there is no reason it would not work on other operating systems (except the bash commands and scripts used below).

How to build and test

If you don't need the SQL linter feature:

$ go build && ./go-parano -dir examples/

If you need the SQL linter feature (version installing and using phpmyadmin/sql-parser using composer):

$ go build && sh test_phpmyadmin_sql-parser.sh

If you need the SQL linter feature (version installing and using sqlfluff using pip):

$ go build && sh test_sqlfluff.sh

It should display something like (example below is the version with phpmyadmin/sql-parser):

INVALID: missing fields(s) foo3, foo4 in declaration "testType1{}" in examples/example1.go, type declared with //!PARANO__EXHAUSTIVE_FILLING in examples/example1.go
INVALID: Cannot use testVarNotOkay in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Cannot use testType2 in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Cannot use testType3 in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Cannot use testFunctionNotOkay in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Cannot use testFunctionNotOkay in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Cannot use localPrivateStuffTest in examples/example1.go, declared as private to file in examples/example2.go
INVALID: Invalid SQL query in examples/example1.go: SELECT FROM JOIN "1";
INVALID:      |_ #1: An expression was expected. (near "FROM" at position 7)
INVALID:      |_ #2: An expression was expected. (near "JOIN" at position 12)
INVALID:      |_ 
INVALID: Invalid SQL query in examples/example1.go: INSERT INTO elements typo mistake (`foo`,`bar`) ...
INVALID:      |_ #1: Unexpected token. (near "typo" at position 21)
INVALID:      |_ #2: Unexpected beginning of statement. (near "typo" at position 21)
INVALID:      |_ #3: Unexpected beginning of statement. (near "mistake" at position 26)
INVALID:      |_ #4: Unexpected beginning of statement. (near "`foo`" at position 35)
INVALID:      |_ #5: Unexpected beginning of statement. (near "`bar`" at position 41)
INVALID:      |_ #6: Unrecognized statement type. (near "VALUES" at position 48)
INVALID:      |_ 
WARNING: Cannot fully check query in file 'examples/example1.go': SELECT * FROM ???
INVALID: missing fields(s) Foo2 in declaration "examplesub.TestTypeSub{}" in examples/example1.go, type declared with //!PARANO__EXHAUSTIVE_FILLING in ???

Features:

Feature: private to file

This gives a way to ensure that a function/type/variable is not used in another file of the same package.

For example:

//!PARANO__PRIVATE_TO_FILE
var i int // ---> i cannot be used in other files of the same package.

Also everything below the line // LOCAL PRIVATE STUFF until the end of file, is also private to file.

Feature: struct exhaustive filling

This gives a way to check that all the fields of a Go struct are informed when that struct is instancied.

//!PARANO__EXHAUSTIVE_FILLING
type testType1 struct {
	foo1 int
	foo2 int
}
...
var testNokFill = testType1{
  foo1: 3, // ---> foo2 is detected as unaffected
}
Feature: SQL linter

This is a way to check that the SQL queries in the Go code are correct.

Basically you define in the arguments of go-parano:

  • the function(s) used for all of your queries, and the argument index in this(these) function(s) containing the query (like examplesub.Query:1) (with -sql-query-func-name)
  • a linter program (with -sql-query-lint-binary)

and it will check all the queries in the functions calls in the source code.

examplesub.Query("SELECT 1") // -> will run the linter program on "SELECT 1"

You can use any linter program as long as:

  • it accepts the query as stdin.
  • it returns nonzero code and a message if there is an error in the query.

Current features:

  • Supports if the query is splitted into several strings concatenated with '+', or even if it contains a constant declared in the current source file.

Current limitations (TODO):

  • What if the function uses a struct as argument and the query is a field in the struct.
  • What if this is a method and not a function e.g. myDBHandle.Query().
  • Limitations depending of the linter programs I tested:
    • '?' (static queries) won't work?
    • Does not check whether the tables and fields exist.

If you don't want to check queries in a function (e.g. false positives), put as a comment //!PARANO__IGNORE_CHECK_SQL_QUERIES on top of the function declaration with the function call, for example:

//!PARANO__IGNORE_CHECK_SQL_QUERIES
func foo() {
	examplesub.Query("SELECT 1")
}

Or use //!PARANO__IGNORE_CHECK_SQL_QUERY within the function call, for example:

examplesub.Query( //!PARANO__IGNORE_CHECK_SQL_QUERY
	"SELECTYYYY")
}

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
src
fileparser
https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87
https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL