/
README.md
214 lines (163 loc) · 5.84 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# souffle-lint
A linter for [Soufflé Datalog][souffle], based on
[tree-sitter-souffle][tree-sitter-souffle], configured with
[tree-sitter queries][tree-sitter-query].
<!--
TODO(lb):
- Warn on parse errors
- More context for each `?`
- More configuration validation
- CI
- Build
- Lint
- Release
- Test
-->
## Contents
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**
- [souffle-lint](#souffle-lint)
- [Contents](#contents)
- [Build and Install](#build-and-install)
- [Build From Source](#build-from-source)
- [Install from a Release](#install-from-a-release)
- [Usage](#usage)
- [Pre-Processing](#pre-processing)
- [Ignoring Rules](#ignoring-rules)
- [Writing Rules](#writing-rules)
- [Showing the Parse Tree](#showing-the-parse-tree)
- [Rule Categories](#rule-categories)
- [Development](#development)
- [Tests](#tests)
- [Benchmarks](#benchmarks)
<!-- markdown-toc end -->
## Build and Install
For now, build from source with `cargo`.
### Build From Source
```bash
git clone https://github.com/langston-barrett/souffle-lint
cargo build --release
```
To install, just copy the binary somewhere:
```
cp target/release/souffle-lint /usr/bin
```
### Install from a Release
TBD. <!-- TODO(lb) -->
## Usage
Just pass a list of Soufflé Datalog files to `souffle-lint lint`, or pass one on
stdin:
```bash
# Lint a single file:
souffle-lint lint file.dl
# Lint a file from stdin:
souffle-lint lint <file.dl
# Lint two files:
souffle-lint lint file.dl path/to/file2.dl
# Lint all the Soufflé Datalog files the current directory:
souffle-lint lint ./**/*.dl
```
The exit code will be `0` if `souffle-lint lint` succeeded with no warnings, `1`
if there were any warnings, or `2` if there was a problem (e.g., a parse error
or bad configuration).
See `--help` for more options.
### Pre-Processing
Soufflé runs the C pre-processor (CPP) on Datalog files by default, and it is
customary for developers to use its functionality. The `souffle-lint` parser
does not handle CPP directives; if you use them you must run the
pre-processor manually and then run `souffle-lint` on the result. For instance,
```bash
mcpp -W 0 -P your/datalog/file.dl -o out.dl
souffle-lint lint out.dl
```
`souffle-lint` doesn't (yet) take advantage of the `#line` directives in the CPP
output, so the line numbers in its output won't correspond to your source file.
<!-- TODO(lb): Use `#line` -->
## Ignoring Rules
Each rule has an associated name. These names are visible in the list shown by
the `info` command, and also in warning messages. For example, in the following
message, the rule name is `error-dup-type-decl`:
```
warn[error-dup-type-decl] Duplicated type declaration
```
You can disable a rule entirely by passing `--ignore=<rule-name>` on the command
line. In fact, you can pass a *prefix* to `--ignore`; any rules that start with
that prefix will be ignored. For example, `--ignore=simpl` will disable any
rules with names starting with `simpl`. See [Rule Categories][#rule-categories]
for information about common prefixes.
Ignoring a specific warning on a specific line is not yet implemented.
<!-- TODO(lb): Implement me!
You can ignore a warning for a specific line by by placing a comment of the form `ignore[<warning-name>]` on the line before, e.g.,
```
// ignore[simpl-binop-id]
one(0 + 1).
```
-->
Rules with slow execution times are disabled by default, you can enable them
with `souffle-lint lint --slow`.
## Writing Rules
The [YAML][yaml] configuration file consists of a list of *rules*. Each rule
has:
- A short name
- A short description
- A list of *queries*
- A list of examples
Here is an example of a simple rule which exhorts its user to simplify
compile-time constant additions:
```yaml
rules:
- name: simpl-binop-plus
short: Simplify constant binary operation (+)
long: >
Some extended description of this rule.
examples:
- before: |
even(2 + 2).
after: |
even(4).
queries:
- |
(binary_op
left: (argument (constant))
operator: "+"
right: (argument (constant)))
```
You can view the built-in configuration file at
[`./config/default.yml`](./config/default.yml).
A query describes a pattern in the program's concrete syntax tree (CST), a rule
triggers a warning when the query matches its CST. Queries are written in the
[tree-sitter query language][tree-sitter-query].
The name should be less than 30 characters, the short description should be less
than 60 characters.
### Showing the Parse Tree
You can see the tree-sitter S-expression (i.e., concrete syntax tree)
corresponding to Datalog source file(s) using the `sexp` command:
```
souffle-lint sexp file.dl
```
See `souffle-lint sexp --help` for more details and other options.
## Rule Categories
By convention, rules have names starting with common prefixes:
- `depr`: This functionality is deprecated
- `error`: Soufflé would reject this code
- `error-dup`: Some entity is duplicated
- `simpl`: The code can be simplified, possibly for better performance
- `simpl-dup`: Some entity is duplicated
- `style`: This is a stylistic choice
- `style-name`: This is a stylistic choice about names
## Development
### Tests
Tested with [lit][lit] and [FileCheck][filecheck]
```bash
cargo build
lit --path=$PWD/target/debug test/
```
### Benchmarks
Large Soufflé files are available in `bench/`. Try passing `--trace` to
`souffle-lint`. Compare performance to `souffle --show=parse-errors`.
[filecheck]: https://www.llvm.org/docs/CommandGuide/FileCheck.html
[lit]: https://llvm.org/docs/CommandGuide/lit.html
[souffle]: https://souffle-lang.github.io/index.html
[tree-sitter-query]: https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax
[tree-sitter-souffle]: https://github.com/langston-barrett/tree-sitter-souffle/
[yaml]: https://yaml.org/