Skip to content

Commit

Permalink
Add a new 'names.reserved' check (#22)
Browse files Browse the repository at this point in the history
This checks allows you to extend the default list of reserved keywords
with additional names.
  • Loading branch information
jparise authored Jul 27, 2021
1 parent a77e536 commit 9a39169
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 1 deletion.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@ Some languages (e.g. JavaScript) don't support 64-bit integers.

This check ensures that only primitive types are used for `map<>` keys.

### `names.reserved`

This checks allows you to extend the [default list of reserved keywords][] with
additional disallowed names.

```toml
[checks.names]
reserved = [
"template",
]
```

[default list of reserved keywords]: https://github.com/thriftrw/thriftrw-go/blob/0cee03e01be6bbbd45303ca94663c951f0573fd0/idl/internal/lex.rl#L110-L218

### `namespace.patterns`

This check ensures that a namespace's name matches a regular expression
Expand Down
10 changes: 10 additions & 0 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ func Doc(node ast.Node) string {
return ""
}

// Name returns an ast.Node's Name string.
func Name(node ast.Node) string {
if v := reflect.ValueOf(node); v.Kind() == reflect.Ptr {
if f := v.Elem().FieldByName("Name"); f.IsValid() {
return f.Interface().(string)
}
}
return ""
}

// Resolve resolves an ast.TypeReference to its target node.
//
// The target can either be in the current program's scope or it can refer to
Expand Down
34 changes: 34 additions & 0 deletions checks/names.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2021 Pinterest
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package checks

import (
"github.com/pinterest/thriftcheck"
"go.uber.org/thriftrw/ast"
)

// CheckNamesReserved checks if a node's name is in the list of reserved names.
func CheckNamesReserved(names []string) *thriftcheck.Check {
reserved := make(map[string]bool)
for _, name := range names {
reserved[name] = true
}

return thriftcheck.NewCheck("names.reserved", func(c *thriftcheck.C, n ast.Node) {
if name := thriftcheck.Name(n); name != "" && reserved[name] {
c.Errorf(n, "%q is a reserved name", name)
}
})
}
50 changes: 50 additions & 0 deletions checks/names_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2021 Pinterest
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package checks_test

import (
"testing"

"github.com/pinterest/thriftcheck/checks"
"go.uber.org/thriftrw/ast"
)

func TestCheckNamesReserved(t *testing.T) {
tests := []Test{
{
node: &ast.Struct{Name: "struct"},
want: []string{},
},
{
node: &ast.Struct{Name: "reserved"},
want: []string{
`t.thrift:0:1:error: "reserved" is a reserved name (names.reserved)`,
},
},
{
node: &ast.Field{Name: "field"},
want: []string{},
},
{
node: &ast.Field{Name: "reserved"},
want: []string{
`t.thrift:0:1:error: "reserved" is a reserved name (names.reserved)`,
},
},
}

check := checks.CheckNamesReserved([]string{"reserved"})
RunTests(t, check, tests)
}
7 changes: 6 additions & 1 deletion cmd/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Note that if any -I options are specified on the command line, they will
# be used instead of this configuration value.
includes = [
'shared',
"shared",
]

# Lists of checks to explicitly enable or disable. If a prefix is given (e.g.
Expand All @@ -26,6 +26,11 @@ error = 1000
[[checks.include.restricted]]
"*" = "(huge|massive).thrift"

[checks.names]
reserved = [
"template",
]

[checks.namespace]
[[checks.namespace.patterns]]
py = "^idl\\."
5 changes: 5 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ type Config struct {
Restricted map[string]string `fig:"restricted"`
}

Names struct {
Reserved []string `fig:"reserved"`
}

Namespace struct {
Patterns map[string]string `fig:"patterns"`
}
Expand Down Expand Up @@ -151,6 +155,7 @@ func main() {
checks.CheckIncludeRestricted(cfg.Checks.Include.Restricted),
checks.CheckInteger64bit(),
checks.CheckMapKeyType(),
checks.CheckNamesReserved(cfg.Checks.Names.Reserved),
checks.CheckNamespacePattern(cfg.Checks.Namespace.Patterns),
checks.CheckSetValueType(),
}
Expand Down

0 comments on commit 9a39169

Please sign in to comment.