From c2f11bfa45396d1b2d51cae059df5bcf14037ecc Mon Sep 17 00:00:00 2001 From: Work-Sadik Date: Tue, 15 Sep 2026 12:05:50 +0530 Subject: [PATCH 1/5] feat(allowlist): support Siemens SCL files --- internal/config/allowlist/supported_file_types.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/config/allowlist/supported_file_types.json b/internal/config/allowlist/supported_file_types.json index 3902a2e00..c5794b8f1 100644 --- a/internal/config/allowlist/supported_file_types.json +++ b/internal/config/allowlist/supported_file_types.json @@ -109,5 +109,6 @@ ".vhdl", ".sol", ".vy", - ".rego" + ".rego", + ".scl" ] From b17766b5e82c1899628f8550a10d378f3c72bbb7 Mon Sep 17 00:00:00 2001 From: Work-Sadik Date: Tue, 15 Sep 2026 12:06:01 +0530 Subject: [PATCH 2/5] feat(rules): add Siemens SCL review guidance --- internal/config/rules/rule_docs/scl.md | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 internal/config/rules/rule_docs/scl.md diff --git a/internal/config/rules/rule_docs/scl.md b/internal/config/rules/rule_docs/scl.md new file mode 100644 index 000000000..d84d86396 --- /dev/null +++ b/internal/config/rules/rule_docs/scl.md @@ -0,0 +1,34 @@ +#### Siemens SCL Review Principles +> Focus on defects that can change PLC behavior, safety, determinism, or runtime reliability. SCL (Structured Control Language) is a Pascal-based textual PLC language aligned with IEC 61131-3 Structured Text. Do not flag ordinary Pascal-like syntax or vendor-specific conventions unless the changed code demonstrates a concrete correctness problem. + +#### Control Flow and State +- Conditions that accidentally omit a required branch, especially when the omitted state leaves an output, command, or state variable holding a stale value +- `CASE` statements that do not cover an expected value when the uncovered state can produce unsafe or incorrect machine behavior +- State-machine transitions that make a state unreachable, create an unintended transition loop, or leave the machine with no valid successor +- Repeated writes to the same control variable in one scan where later assignments can silently override an earlier decision + +#### Loops and Scan-Time Safety +- Loops whose termination depends on mutable PLC state without a clear progress condition +- Unbounded or unexpectedly large loops in cyclic program execution when they can exceed the expected scan-time budget or starve time-critical logic +- Busy-wait loops used where a state transition, timer, or other PLC-supported sequencing mechanism is needed + +#### Data Types and Numeric Correctness +- Implicit conversions or narrowing assignments that can truncate a value, change signedness, or lose precision in a way that affects control logic +- Arithmetic whose range can exceed the target data type, especially counters, timers, indexes, and accumulated values +- Array indexing that can reach outside the declared bounds because the index is derived from runtime input or an unchecked calculation +- Comparisons between values with incompatible or unintended types where the result can differ from the programmer's apparent intent + +#### I/O and Persistent Data +- Writing outputs or persistent state before required validity, mode, or interlock checks have completed +- Reading an input once and then using a stale snapshot across logic that can change the relevant machine state within the same scan +- Resetting, overwriting, or reinitializing retained/process data unexpectedly, causing loss of state across cycles or restarts + +#### Error Handling and External Blocks +- Ignoring a status/error result from a called block or communication operation when the caller continues as though the operation succeeded +- Using data produced by a block, timer, counter, or communication interface before establishing that the result is valid for the current state +- Error paths that leave an actuator command, mode bit, or state variable in an unsafe or contradictory condition + +#### Maintainability with Behavioral Impact +- Duplicated control conditions that can diverge after a change and cause two parts of the sequence to make conflicting decisions +- Magic constants used for operational limits where the value is part of a safety, timing, or process invariant and can be changed independently of the corresponding logic +- Dead branches or unreachable code when their presence can hide a missing transition or an incomplete safety condition From 813637aecaf7d6f5662a020ac6759bcc1bb0e13a Mon Sep 17 00:00:00 2001 From: Work-Sadik Date: Tue, 15 Sep 2026 12:06:05 +0530 Subject: [PATCH 3/5] test(allowlist): cover Siemens SCL extension --- internal/config/allowlist/scl_ext_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 internal/config/allowlist/scl_ext_test.go diff --git a/internal/config/allowlist/scl_ext_test.go b/internal/config/allowlist/scl_ext_test.go new file mode 100644 index 000000000..8170e7855 --- /dev/null +++ b/internal/config/allowlist/scl_ext_test.go @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2026 alibaba/open-code-review Contributors + +package allowedext + +import "testing" + +func TestSCLIsAllowedCaseInsensitive(t *testing.T) { + for _, ext := range []string{".scl", ".SCL"} { + t.Run(ext, func(t *testing.T) { + if !IsAllowedExt(ext) { + t.Fatalf("IsAllowedExt(%q) = false, want true", ext) + } + }) + } +} From bbd2589ae46764d96bc388846a0fc2bc1e4e2506 Mon Sep 17 00:00:00 2001 From: Work-Sadik Date: Tue, 15 Sep 2026 12:06:12 +0530 Subject: [PATCH 4/5] feat(rules): map SCL files to dedicated guidance --- internal/config/rules/system_rules.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/config/rules/system_rules.json b/internal/config/rules/system_rules.json index f14164595..1cef005bc 100644 --- a/internal/config/rules/system_rules.json +++ b/internal/config/rules/system_rules.json @@ -52,6 +52,7 @@ "**/*.mm": "objc.md", "**/*.sol": "solidity.md", "**/*.vy": "vyper.md", - "**/*.rego": "rego.md" + "**/*.rego": "rego.md", + "**/*.scl": "scl.md" } } From cb08652b643b6c02a353548759ee14349cb70d51 Mon Sep 17 00:00:00 2001 From: Work-Sadik Date: Tue, 15 Sep 2026 12:06:16 +0530 Subject: [PATCH 5/5] test(rules): cover Siemens SCL rule resolution --- internal/config/rules/scl_rules_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/config/rules/scl_rules_test.go diff --git a/internal/config/rules/scl_rules_test.go b/internal/config/rules/scl_rules_test.go new file mode 100644 index 000000000..273e99b52 --- /dev/null +++ b/internal/config/rules/scl_rules_test.go @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2026 alibaba/open-code-review Contributors + +package rules + +import ( + "strings" + "testing" +) + +func TestResolve_SCLRule(t *testing.T) { + rule, err := LoadDefault() + if err != nil { + t.Fatalf("LoadDefault: %v", err) + } + + for _, path := range []string{"main.scl", "plc/Blocks/Motor.SCL", "src/control.scl"} { + t.Run(path, func(t *testing.T) { + got := rule.Resolve(path) + if !strings.Contains(got, "Siemens SCL Review Principles") { + t.Fatalf("Resolve(%q): expected Siemens SCL rule, got %q", path, truncate(got, 120)) + } + }) + } +}