Beacon Linter
The Beacon Rule Engine is a modular static analysis system powering diagnostics in Beacon.
It's foundationally a pure Rust implementation of PyFlakes.
Legend: ⚠ = Warning ✕ = Error ⓘ = Info
| Code | Name / RuleKind | Level | Category | Description |
|---|---|---|---|---|
| BEA001 | UndefinedName | ✕ | Naming | Variable or function used before being defined. |
| BEA002 | DuplicateArgument | ✕ | Functions | Duplicate parameter names in a function definition. |
| BEA003 | ReturnOutsideFunction | ✕ | Flow | return statement outside of a function or method body. |
| BEA004 | YieldOutsideFunction | ✕ | Flow | yield or yield from used outside a function context. |
| BEA005 | BreakOutsideLoop | ✕ | Flow | break used outside a for/while loop. |
| BEA006 | ContinueOutsideLoop | ✕ | Flow | continue used outside a for/while loop. |
| BEA007 | DefaultExceptNotLast | ⚠ | Exception | A bare except: is not the final exception handler in a try block. |
| BEA008 | RaiseNotImplemented | ⚠ | Semantics | Using raise NotImplemented instead of raise NotImplementedError. |
| BEA009 | TwoStarredExpressions | ✕ | Syntax | Two or more * unpacking expressions in assignment. |
| BEA010 | TooManyExpressionsInStarredAssignment | ✕ | Syntax | Too many expressions when unpacking into a starred target. |
| BEA011 | IfTuple | ⚠ | Logic | A tuple literal used as an if condition — always True. |
| BEA012 | AssertTuple | ⚠ | Logic | Assertion always true due to tuple literal. |
| BEA013 | FStringMissingPlaceholders | ⚠ | Strings | f-string declared but contains no {} placeholders. |
| BEA014 | TStringMissingPlaceholders | ⚠ | Strings | t-string declared but contains no placeholders. |
| BEA015 | UnusedImport | ⚠ | Symbols | Import is never used within the file. |
| BEA016 | UnusedVariable | ⚠ | Symbols | Local variable assigned but never used. |
| BEA017 | UnusedAnnotation | ⚠ | Symbols | Annotated variable never referenced. |
| BEA018 | RedefinedWhileUnused | ⚠ | Naming | Variable redefined before original was used. |
| BEA019 | ImportShadowedByLoopVar | ⚠ | Scope | Import name shadowed by a loop variable. |
| BEA020 | ImportStarNotPermitted | ✕ | Imports | from module import * used inside a function or class. |
| BEA021 | ImportStarUsed | ⚠ | Imports | import * prevents detection of undefined names. |
| BEA022 | UnusedIndirectAssignment | ⚠ | Naming | Global or nonlocal declared but never reassigned. |
| BEA023 | ForwardAnnotationSyntaxError | ✕ | Typing | Syntax error in forward type annotation. |
| BEA024 | MultiValueRepeatedKeyLiteral | ⚠ | Dict | Dictionary literal repeats key with different values. |
| BEA025 | PercentFormatInvalidFormat | ⚠ | Strings | Invalid % format string. |
| BEA026 | IsLiteral | ⚠ | Logic | Comparing constants with is or is not instead of ==/!=. |
| BEA027 | DefaultExceptNotLast | ⚠ | Exception | Bare except: must appear last. |
| BEA028 | UnreachableCode | ⚠ | Flow | Code after a return, raise, or break is never executed. |
| BEA029 | RedundantPass | ⓘ | Cleanup | pass used in a block that already has content. |
| BEA030 | EmptyExcept | ⚠ | Exception | except: with no handling code (silent failure). |
Rules
BEA001
Example
print(foo) before foo is defined.
Fix
Define the variable before use or fix the typo.
BEA002
Example
def f(x, x):
pass
Fix
Rename one of the parameters.
BEA003
Example
Top-level return 5 in a module.
Fix
Remove or move inside a function.
BEA004
Example
yield x at module scope.
Fix
Wrap in a generator function.
BEA005
Example
break in global scope or in a function without loop.
Fix
Remove or restructure the code to include a loop.
BEA006
Example
continue in a function with no loop.
Fix
Remove or replace with control flow logic.
BEA007
Example
except: followed by except ValueError:
Fix
Move the except: block to the end of the try.
BEA008
Example
raise NotImplemented
Fix
Replace with raise NotImplementedError.
BEA009
Example
a, *b, *c = d
Fix
Only one starred target is allowed.
BEA010
Example
a, b, c, d = (1, 2, 3)
Fix
Adjust unpacking count.
BEA011
Example
if (x,):
...
Fix
Remove accidental comma or rewrite condition.
BEA012
Example
assert (x, y)
Fix
Remove parentheses or fix expression.
BEA013
Example
f"Hello world"
Fix
Remove the f prefix if unnecessary.
BEA014
Example
t"foo"
Fix
Remove the t prefix if unused.
BEA015
Example
import os not referenced.
Fix
Remove the unused import.
BEA016
Example
x = 10 never referenced again.
Fix
Remove assignment or prefix with _ if intentional.
BEA017
Example
x: int declared but unused.
Fix
Remove or use variable.
BEA018
Example
x = 1; x = 2 without reading x.
Fix
Remove unused definition.
BEA019
Example
import os
for os in range(3):
...
Fix
Rename loop variable.
BEA020
Example
def f():
from math import *
Fix
Move import to module level.
BEA021
Example
from os import *
Fix
Replace with explicit imports.
BEA022
Example
global foo never used.
Fix
Remove redundant declaration.
BEA023
Example
def f() -> "List[int": ...
Fix
Fix or quote properly.
BEA024
Example
{'a': 1, 'a': 2}
Fix
Merge or remove duplicate keys.
BEA025
Example
"%q" % 3
Fix
Correct format specifier.
BEA026
Example
x is 5
Fix
Use ==/!=.
BEA027
Example
As above.
Fix
Reorder exception handlers.
BEA028
Example
return 5; print("unreachable")
Fix
Remove or refactor code.
BEA029
Example
def f():
pass
return 1
Fix
Remove redundant pass.
BEA030
Example
try:
...
except:
pass
Fix
Handle exception or remove block.
Planned
| Name | Kind | Category | Severity | Rationale |
|---|---|---|---|---|
| Mutable Default Argument | MutableDefaultArgument | Semantic | ✕ | Detect functions that use a mutable object (e.g., list, dict, set) as a default argument. |
| Return in Finally | ReturnInFinally | Flow | ✕ | Catch a return, break, or continue inside a finally block: this often suppresses the original exception and leads to subtle bugs. |
| For-Else Without Break | ForElseWithoutBreak | Flow | ⚠ | The for ... else construct where the else never executes a break is confusing and often mis-used. If you have else: on a loop but never break, you may signal confusing logic. |
| Wrong Exception Caught | BroadExceptionCaught | Exception | ⚠ | Catching too broad exceptions (e.g., except Exception: or except:) instead of specific types can hide bugs. You already have empty except; this expands to overly broad catching. |
| Inconsistent Return Types | InconsistentReturnTypes | Function | ⚠ | A function that returns different types on different paths (e.g., return int in one branch, return None in another) may lead to consuming code bugs especially if not annotated. |
| Index / Key Errors Likely | UnsafeIndexOrKeyAccess | Data | ⚠ | Detect patterns that likely lead to IndexError or KeyError, e.g., accessing list/dict without checking length/keys, especially inside loops. |
| Unused Coroutine / Async Function | UnusedCoroutine | Symbol | ⚠ | In async code: a async def function is defined but neither awaited nor returned anywhere — likely a bug. |
| Resource Leak / Unclosed Descriptor | UnclosedResource | Symbol | ⚠ | Detect file or network resource opened (e.g., open(...)) without being closed or managed via context manager (with). |
| Logging Format String Errors | LoggingFormatError | String | ⚠ | Using % or f-string incorrectly in logging calls (e.g., logging format mismatches number of placeholders) can cause runtime exceptions or silent failures. |
| Comparison to None Using == / != | NoneComparison | Logic | ⚠ | Discourage == None or != None in favor of is None / is not None. |