From 92735f3eeef9061b03504598f23d6c1347a8a4f0 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Mon, 2 Jun 2025 12:00:15 +0300 Subject: [PATCH] docs: update README with new features --- README.md | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 366 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4242213..7368374 100644 --- a/README.md +++ b/README.md @@ -30,26 +30,68 @@ supported, I cannot guarantee that _everything_ is supported just yet. - **Validation** - Syntax checking with precise error locations - **Optimization** - Configurable empty line reduction and whitespace control +### Diagnostics & Analysis + +- **Comprehensive diagnostics** - Syntax, semantic, style, and best practice + analysis +- **Modular analysis** - Run specific diagnostic modules (`lexical`, `syntax`, + `style`, `semantic`) +- **LSP-compatible output** - JSON format for editor integration +- **Human-readable reports** - Detailed error messages with context and location + information +- **Configurable severity** - Control which diagnostic categories to + enable/disable + ## Usage +### Formatting + ```bash -# Basic formatting -nff -f /etc/nftables.conf +# Format a specific file (in place) +nff format /etc/nftables.conf + +# Format all .nft files in current directory (in place) +nff format # Custom indentation (4 spaces) -nff -f config.nft --indent spaces --spaces 4 +nff format config.nft --indent spaces --spaces 4 # Optimize formatting (reduce empty lines) -nff -f config.nft --optimize +nff format config.nft --optimize -# Output to file -nff -f config.nft -o formatted.nft +# Output to stdout instead of modifying files +nff format config.nft --stdout # Syntax validation only -nff -f config.nft --check +nff format config.nft --check # Debug output for development (or debugging) -nff -f config.nft --debug +nff format config.nft --debug +``` + +### Linting and Diagnostics + +```bash +# Run comprehensive diagnostics on a file +nff lint /etc/nftables.conf + +# Lint all .nft files in current directory +nff lint + +# JSON output for editor integration +nff lint config.nft --json + +# Run specific diagnostic modules +nff lint config.nft --modules syntax,style + +# Available modules: lexical, syntax, style, semantic +nff lint config.nft --modules semantic + +# Configure diagnostic settings (note: flags are enabled by default) +nff lint config.nft --style-warnings=false --best-practices=false + +# Debug output with diagnostics +nff lint config.nft --debug ``` ## Architecture @@ -69,12 +111,235 @@ graph TD AST --> Formatter Formatter --> Output CST --> Formatter + + Input --> Diagnostics[Diagnostic System] + Diagnostics --> LexAnalyzer[Lexical Analyzer] + Diagnostics --> SyntaxAnalyzer[Syntax Analyzer] + Diagnostics --> StyleAnalyzer[Style Analyzer] + Diagnostics --> SemanticAnalyzer[Semantic Analyzer] + + LexAnalyzer --> DiagOutput[JSON/Human Output] + SyntaxAnalyzer --> DiagOutput + StyleAnalyzer --> DiagOutput + SemanticAnalyzer --> DiagOutput ``` ## Installation Recommended way of installing nff is to use Nix. +### Editor Integration + +#### Neovim Setup + +nff can be integrated into Neovim as a diagnostics source for nftables files. +Here are several setup approaches: + +##### Option 2: Using none-ls + +```lua +local null_ls = require("null-ls") + +null_ls.setup({ + sources = { + -- nftables diagnostics + null_ls.builtins.diagnostics.nff.with({ + command = "nff", + args = { "lint", "$FILENAME", "--json" }, + format = "json", + check_exit_code = false, + filetypes = { "nftables" }, + }), + + -- nftables formatting + null_ls.builtins.formatting.nff.with({ + command = "nff", + args = { "format", "$FILENAME", "--stdout" }, + filetypes = { "nftables" }, + }), + }, +}) +``` + +##### Option 2: Using nvim-lint (recommended) + +```lua +-- ~/.config/nvim/lua/config/lint.lua +require('lint').linters.nff = { + cmd = 'nff', + stdin = false, + args = { 'lint', '%s', '--json' }, + stream = 'stdout', + ignore_exitcode = true, + parser = function(output) + local diagnostics = {} + local ok, decoded = pcall(vim.fn.json_decode, output) + + if not ok or not decoded.diagnostics then + return diagnostics + end + + for _, diagnostic in ipairs(decoded.diagnostics) do + table.insert(diagnostics, { + lnum = diagnostic.range.start.line, + col = diagnostic.range.start.character, + severity = diagnostic.severity == "Error" and vim.diagnostic.severity.ERROR or vim.diagnostic.severity.WARN, + message = diagnostic.message, + source = "nff", + code = diagnostic.code, + }) + end + + return diagnostics + end, +} + +-- Setup linting for nftables files +vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost" }, { + pattern = "*.nft", + callback = function() + require("lint").try_lint("nff") + end, +}) +``` + +##### Option 3: Custom Lua Function + +For a simple custom solution: + +```lua +-- ~/.config/nvim/lua/nff.lua +local M = {} + +function M.lint_nftables() + local filename = vim.fn.expand('%:p') + if vim.bo.filetype ~= 'nftables' then + return + end + + local cmd = { 'nff', 'lint', filename, '--json' } + + vim.fn.jobstart(cmd, { + stdout_buffered = true, + on_stdout = function(_, data) + if data then + local output = table.concat(data, '\n') + local ok, result = pcall(vim.fn.json_decode, output) + + if ok and result.diagnostics then + local diagnostics = {} + for _, diag in ipairs(result.diagnostics) do + table.insert(diagnostics, { + lnum = diag.range.start.line, + col = diag.range.start.character, + severity = diag.severity == "Error" and vim.diagnostic.severity.ERROR or vim.diagnostic.severity.WARN, + message = diag.message, + source = "nff", + }) + end + + vim.diagnostic.set(vim.api.nvim_create_namespace('nff'), 0, diagnostics) + end + end + end, + }) +end + +-- Auto-run on save +vim.api.nvim_create_autocmd("BufWritePost", { + pattern = "*.nft", + callback = M.lint_nftables, +}) + +return M +``` + +## Diagnostic Categories + +nff provides comprehensive analysis across multiple categories: + +### Syntax Errors + +- Parse errors with precise location information +- Missing tokens (semicolons, braces, etc.) +- Unexpected tokens +- Unterminated strings +- Invalid numbers + +### Semantic Validation + +- Unknown table families (`inet`, `ip`, `ip6`, etc.) +- Invalid chain types and hooks +- Incorrect priority values +- Missing chain policies +- Duplicate table/chain names +- Invalid CIDR notation +- Invalid port ranges + +### Style Warnings + +- Missing shebang line +- Inconsistent indentation (mixed tabs/spaces) +- Trailing whitespace +- Lines exceeding maximum length (configurable) +- Excessive empty lines +- Preferred syntax alternatives + +### Best Practices + +- Chains without explicit policies +- Rules without actions +- Overly permissive rules +- Duplicate or conflicting rules +- Unused variables or sets +- Deprecated syntax usage +- Missing documentation +- Security risks + +### Performance Hints + +- Inefficient rule ordering +- Large sets without timeouts +- Missing counters where beneficial + +## JSON Output Format + +When using `--json`, nff outputs LSP-compatible diagnostics: + +```json +{ + "diagnostics": [ + { + "range": { + "start": { "line": 5, "character": 10 }, + "end": { "line": 5, "character": 20 } + }, + "severity": "Error", + "code": "NFT001", + "source": "nff", + "message": "Expected ';' after policy", + "related_information": [], + "code_actions": [], + "tags": [] + } + ], + "file_path": "config.nft", + "source_text": "..." +} +``` + +### Diagnostic Codes + +nff uses structured diagnostic codes for categorization: + +- **NFT001-NFT099**: Syntax errors +- **NFT101-NFT199**: Semantic errors +- **NFT201-NFT299**: Style warnings +- **NFT301-NFT399**: Best practice recommendations +- **NFT401-NFT499**: Performance hints +- **NFT501-NFT599**: Formatting issues +- **NFT601-NFT699**: nftables-specific validations + ## Development ### Testing @@ -196,6 +461,88 @@ table inet protection { } ``` +## Diagnostics Examples + +### Error Detection + +Input file with issues: + +```nftables +table inet firewall { + chain input { + type filter hook input priority 100 + tcp dport 22 accept + } +} +``` + +Human-readable output: + +``` +Found 2 issues in config.nft: +config.nft:3:37: error: Expected ';' after policy [NFT001] + 1: table inet firewall { + 2: chain input { +→ 3: type filter hook input priority 100 + 4: tcp dport 22 accept + 5: } + +config.nft:3:1: warning: Filter chain should have an explicit policy [NFT301] + 1: table inet firewall { + 2: chain input { +→ 3: type filter hook input priority 100 + 4: tcp dport 22 accept + 5: } +``` + +JSON output: + +```json +{ + "diagnostics": [ + { + "range": { + "start": { "line": 2, "character": 37 }, + "end": { "line": 2, "character": 37 } + }, + "severity": "Error", + "code": "NFT001", + "source": "nff", + "message": "Expected ';' after policy" + }, + { + "range": { + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 37 } + }, + "severity": "Warning", + "code": "NFT301", + "source": "nff", + "message": "Filter chain should have an explicit policy" + } + ], + "file_path": "config.nft", + "source_text": "..." +} +``` + +### Style Analysis + +Input with style issues: + +```nftables +table inet test{chain input{type filter hook input priority 0;policy drop;tcp dport 22 accept;}} +``` + +Style warnings: + +``` +Found 3 issues in style.nft: +style.nft:1:1: warning: Consider adding a shebang line [NFT201] +style.nft:1:121: warning: Line too long (98 > 80 characters) [NFT205] +style.nft:1:16: warning: Missing space after '{' [NFT503] +``` + ## Contributing ### Code Style @@ -237,6 +584,17 @@ Below are the design goals of nff's architechture. - **Memory efficiency**: Streaming token processing where possible - **Grammar completeness**: Covers full nftables syntax specification +### Diagnostic Architecture + +The diagnostic system uses a modular architecture with specialized analyzers: + +- **Modular design**: Each analyzer focuses on specific concerns (lexical, + syntax, style, semantic) +- **Configurable analysis**: Enable/disable specific diagnostic categories +- **LSP compatibility**: JSON output follows Language Server Protocol standards +- **Performance optimized**: Concurrent analysis when possible +- **Extensible**: Easy to add new diagnostic rules and categories + ## License nff is licensed under [MPL v2.0](LICENSE). See license file for more details on