breadkit-lint 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yamllint +16 -0
- data/CHANGELOG.md +30 -2
- data/README.md +55 -40
- data/action.yml +42 -0
- data/config/default.yml +33 -0
- data/docs/REFERENCE.md +129 -0
- data/docs/rules/Electrical/CapacitorVoltageRating.md +5 -0
- data/docs/rules/Electrical/FloatingInput.md +11 -0
- data/docs/rules/Electrical/GpioOvercurrent.md +18 -0
- data/docs/rules/Electrical/I2CAddressConflict.md +5 -0
- data/docs/rules/Electrical/I2CPullupMissing.md +5 -0
- data/docs/rules/Electrical/LedOvercurrent.md +5 -0
- data/docs/rules/Electrical/MinimumResistance.md +14 -0
- data/docs/rules/Electrical/MissingBaseResistor.md +5 -0
- data/docs/rules/Electrical/MissingDecouplingCapacitor.md +5 -0
- data/docs/rules/Electrical/MissingFlybackDiode.md +18 -0
- data/docs/rules/Electrical/MissingPullResistor.md +17 -0
- data/docs/rules/Electrical/MissingSeriesResistor.md +3 -1
- data/docs/rules/Electrical/NoCommonGround.md +1 -0
- data/docs/rules/Electrical/RailPolarityMismatch.md +10 -0
- data/docs/rules/Electrical/ResistorPowerRating.md +5 -0
- data/docs/rules/Electrical/ReversePolarity.md +1 -1
- data/docs/rules/Electrical/SupplyOverload.md +11 -0
- data/docs/rules/Electrical/SupplyVoltageRange.md +1 -0
- data/docs/rules/Electrical/VoltageDomainMismatch.md +6 -0
- data/docs/rules/Intent/ConnectionMismatch.md +3 -1
- data/docs/rules/Intent/MeasurementUnavailable.md +10 -0
- data/docs/rules/Layout/AmbiguousSupplySource.md +5 -0
- data/docs/rules/Layout/BodyOverlap.md +11 -0
- data/docs/rules/Layout/HoleCovered.md +11 -0
- data/docs/rules/Layout/InvalidColor.md +3 -0
- data/docs/rules/Layout/InvalidOption.md +3 -0
- data/docs/rules/Layout/InvalidRoute.md +3 -0
- data/docs/rules/Layout/InvalidValue.md +3 -0
- data/docs/rules/Layout/InvalidWireId.md +3 -0
- data/docs/rules/Layout/LeadSpan.md +21 -0
- data/docs/rules/Layout/PartOverride.md +3 -0
- data/docs/rules/Layout/UnknownSupplySource.md +5 -0
- data/docs/rules/Layout/UnmatchedParts.md +3 -0
- data/docs/rules/Layout/WireOverIC.md +11 -0
- data/docs/rules/Lint/RedundantDisable.md +3 -0
- data/docs/rules/Lint/UnknownRuleInDisable.md +5 -0
- data/lib/breadkit/lint/baseline.rb +38 -0
- data/lib/breadkit/lint/rake_task.rb +22 -0
- data/lib/breadkit/lint/rules/electrical.rb +580 -30
- data/lib/breadkit/lint/rules/intent.rb +69 -4
- data/lib/breadkit/lint/rules/layout.rb +148 -0
- data/lib/breadkit/lint/rules/style.rb +36 -7
- data/lib/breadkit/lint/rules/support.rb +45 -11
- data/lib/breadkit/lint/rules.rb +205 -2
- data/lib/breadkit/lint/source_editor.rb +138 -0
- data/lib/breadkit/lint/version.rb +1 -1
- data/lib/breadkit/lint.rb +422 -59
- data/lib/guard/breadkit/templates/Guardfile +7 -0
- data/lib/guard/breadkit.rb +26 -0
- data/locales/en.yml +82 -0
- data/locales/ja.yml +130 -4
- data/locales/ko.yml +191 -0
- data/locales/zh.yml +191 -0
- data/package-lock.json +103 -0
- data/package.json +2 -1
- data/scripts/action-run.sh +51 -0
- data/scripts/build-rule-pages.mjs +87 -0
- data/scripts/check-rule-pages.mjs +18 -0
- data/scripts/pre-commit +24 -0
- data/sig/breadkit/lint.rbs +12 -1
- data/site/index.html +9 -6
- data/site/schemas/lint-v1.json +71 -0
- data/site/styles.css +13 -0
- metadata +64 -4
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Intent/MeasurementUnavailable
|
|
2
|
+
|
|
3
|
+
An `expect_voltage` or `expect_current` declaration cannot be checked because
|
|
4
|
+
the DC model has no value for that net or component. The warning includes the
|
|
5
|
+
reason, such as an active GPIO output with an unknown drive state or a floating
|
|
6
|
+
voltage reference.
|
|
7
|
+
|
|
8
|
+
Connect a grounded source and supported passive parts, or check the circuit
|
|
9
|
+
with a simulator that models the unsupported device. This warning does not
|
|
10
|
+
mean the declared range passed.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Layout/AmbiguousSupplySource
|
|
2
|
+
|
|
3
|
+
`supply from:` refers to a pin that matches more than one provided power output. Give each output a distinct positive pin in the part definition so the source has one matching return pin and voltage.
|
|
4
|
+
|
|
5
|
+
This error prevents dependent electrical checks from running because the intended source cannot be determined.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Layout/BodyOverlap
|
|
2
|
+
|
|
3
|
+
Two component bodies intersect even though their leads use different holes. This rule checks rectangular modules with `render.size_mm`, DIP bodies whose complete pin rows establish their position, and circular 5 mm LED bodies (`led_5mm` or `rgb_led_5mm`). Touching edges do not count as an overlap.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
board :half
|
|
7
|
+
led :D1, anode: "a10", cathode: "a11"
|
|
8
|
+
led :D2, anode: "b11", cathode: "b12"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Move one part until its body clears the other. The DIP rectangle follows the rendered body between its pin rows; incomplete or misaligned DIP placements are skipped. Other component shapes without reliable body dimensions are not checked. Module comparisons are skipped when the installed Breadkit version cannot provide body bounds.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Layout/HoleCovered
|
|
2
|
+
|
|
3
|
+
A module or DIP body covers a hole used by another component lead or an electrical wire endpoint. The check uses the module's `render.size_mm`, or a complete DIP pin arrangement, and physical hole positions. Move the lead or wire endpoint to a visible hole; a hole on the same conductive strip is fine if it is outside the body.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
board :half
|
|
7
|
+
part :U1, :pico, at: "d1"
|
|
8
|
+
resistor :R1, "330", pins: %w[e10 a25] # e10 is under U1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The owner's own pins, holes on the body boundary, and visual wires (`electrical: false`) are ignored. A standard DIP sits in the breadboard ravine, so it normally covers no holes. Module checks are skipped when an older Breadkit version cannot provide body geometry.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Layout/LeadSpan
|
|
2
|
+
|
|
3
|
+
A two-lead part is placed farther apart than its declared `max_lead_span_mm`. The rule measures the straight-line distance between the two board holes using the board's 2.54 mm pitch.
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
id: limited_resistor
|
|
7
|
+
category: passive
|
|
8
|
+
placement: leads
|
|
9
|
+
pins:
|
|
10
|
+
- {num: 1, name: "1"}
|
|
11
|
+
- {num: 2, name: "2"}
|
|
12
|
+
max_lead_span_mm: 7.62
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
board :half
|
|
17
|
+
use_parts "limited_resistor.yml"
|
|
18
|
+
part :R1, :limited_resistor, pins: %w[a10 a14] # 10.16 mm exceeds 7.62 mm
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Move the holes closer together or choose a part with a suitable lead span. Parts without declared `max_lead_span_mm` and incomplete placements are skipped; the rule does not assume a generic lead length.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Layout/UnknownSupplySource
|
|
2
|
+
|
|
3
|
+
`supply from:` refers to a pin that is not a provided power output of an offboard component. Check the component reference and choose one of its declared power outputs, such as `UNO.5V`.
|
|
4
|
+
|
|
5
|
+
This error prevents dependent electrical checks from running because the intended source cannot be connected.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Layout/WireOverIC
|
|
2
|
+
|
|
3
|
+
A straight electrical jumper crosses a DIP IC body in the layout. This informational finding helps when planning a build where the jumper should not pass above the chip. Route the wire around the chip if clearance matters.
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
board :half
|
|
7
|
+
ic :U1, :ne555, at: "e10"
|
|
8
|
+
wire "a11", "j11" # Crosses U1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The rule estimates the standard DIP body from all placed pins: it requires two pin rows separated by three hole pitches. It checks only straight electrical wires whose endpoints are board holes. Curved and edge routes, visual alternatives, incomplete ICs, and non-DIP packages are outside this check.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Breadkit
|
|
4
|
+
module Lint
|
|
5
|
+
class Baseline
|
|
6
|
+
def initialize(path)
|
|
7
|
+
@path = File.expand_path(path)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def write(files)
|
|
11
|
+
raise Error, "cannot baseline fatal errors" if files.any? { |file| file[:offenses].any? { |item| item.rule.start_with?("Fatal/") } }
|
|
12
|
+
|
|
13
|
+
entries = files.flat_map { |file| file[:offenses].map { |item| entry(file, item) } }.uniq
|
|
14
|
+
File.write(@path, JSON.pretty_generate(schema_version: 1, entries: entries) + "\n", encoding: "UTF-8")
|
|
15
|
+
entries.length
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def filter(files)
|
|
19
|
+
data = JSON.parse(File.read(@path, encoding: "UTF-8"))
|
|
20
|
+
raise Error, "invalid baseline: expected schema_version 1 and entries" unless data.is_a?(Hash) && data["schema_version"] == 1 && data["entries"].is_a?(Array) && data["entries"].all? { |item| item.is_a?(Hash) }
|
|
21
|
+
|
|
22
|
+
known = data["entries"].to_set
|
|
23
|
+
files.map { |file| file.merge(offenses: file[:offenses].reject { |item| !item.rule.start_with?("Fatal/") && known.include?(entry(file, item)) }) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def entry(file, item)
|
|
29
|
+
path = item.location&.path || file[:path]
|
|
30
|
+
relative = Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(File.dirname(@path))).to_s.tr("\\", "/")
|
|
31
|
+
targets = item.targets.to_h.sort_by { |key, _value| key.to_s }.to_h.transform_keys(&:to_s)
|
|
32
|
+
.transform_values { |value| Array(value).map(&:to_s).sort }
|
|
33
|
+
{ "path" => relative, "rule" => item.rule, "severity" => item.severity,
|
|
34
|
+
"message" => item.message, "state" => item.state, "targets" => targets }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake/tasklib"
|
|
4
|
+
require "breadkit/lint"
|
|
5
|
+
|
|
6
|
+
module Breadkit
|
|
7
|
+
class RakeTask < Rake::TaskLib
|
|
8
|
+
attr_accessor :files, :options
|
|
9
|
+
|
|
10
|
+
def initialize(name = :breadkit)
|
|
11
|
+
super()
|
|
12
|
+
@files = []
|
|
13
|
+
@options = []
|
|
14
|
+
yield self if block_given?
|
|
15
|
+
desc "Lint Breadkit circuits"
|
|
16
|
+
task name do
|
|
17
|
+
status = Breadkit::Lint::CLI.new.run(Array(options) + Array(files))
|
|
18
|
+
raise Breadkit::Lint::Error, "bklint failed with status #{status}" unless status.zero?
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|