diff --git a/Makefile b/Makefile index f12cdb379fc..a6f4166f50c 100644 --- a/Makefile +++ b/Makefile @@ -352,7 +352,23 @@ lint-config-check: $(GOTOOL) $(GOLINT_PKG) config verify -v #? lint: Run static code analysis -lint: check-go-version lint-config-check lint-source +lint: check-go-version lint-config-check lint-source + +# Globs to exclude generated files from ast-grep. +AST_GREP_EXCLUDE := --globs '!**/*.pb.go' --globs '!**/*.pb.gw.go' --globs '!**/*.pb.json.go' --globs '!**/sqlc/*.go' + +# Optional directory/package filter for ast-grep (e.g., make ast-lint pkg=lnwallet). +AST_GREP_PATH := $(if $(pkg),$(pkg),.) + +#? ast-lint: Run ast-grep style checks. Use pkg=
+ case b:
+
+ }
+
+ RIGHT:
+ switch x {
+ // Comment for case a.
+ case a:
+
+
+ case b:
+
+ }
+rule:
+ any:
+ - kind: expression_switch_statement
+ - kind: type_switch_statement
+ # Detects case/default following } or ) without blank line
+ # Pattern: closing brace/paren, newline, tab, then case/default keyword
+ regex: "[)}]\\n\\t(case|default)"
+---
+# Rule: Select cases should be separated by blank lines.
+id: select-case-needs-spacing
+language: go
+severity: hint
+message: "Select cases should be separated by blank lines"
+note: |
+ Per docs/development_guidelines.md: We favor spacing between stanzas within
+ select statements.
+
+ WRONG:
+ select {
+ case <-ch1:
+
+ case <-ch2:
+
+ }
+
+ RIGHT:
+ select {
+ case <-ch1:
+
+
+ case <-ch2:
+
+ }
+rule:
+ kind: select_statement
+ # Detects case/default following } or ) without blank line
+ regex: "[)}]\\n\\t(case|default)"
+---
+# Rule: No inline comments - comments should be on their own line.
+# Detects inline comments by matching composite literals that contain
+# lines with code followed by // comment on the same line.
+id: no-inline-comments
+language: go
+severity: warning
+message: "Inline comment should be on its own line above the code"
+note: |
+ Comments should be on their own line above the code they describe,
+ not at the end of a line.
+
+ WRONG:
+ ChanStatusDefault, // Default status
+ Amount: 100, // The amount in satoshis.
+
+ RIGHT:
+ // Default status.
+ ChanStatusDefault,
+
+ // The amount in satoshis.
+ Amount: 100,
+rule:
+ kind: literal_value
+ has:
+ kind: comment
+ # Match literals containing inline comments: code followed by // on same line.
+ # The key is [^\n] before // ensures they're on the same line.
+ # Pattern: (something other than newline/whitespace), optional spaces, // comment, newline
+ regex: "[a-zA-Z0-9_)\"'\\]},][ \\t]*//[^\\n]*\\n"
diff --git a/rules/go-func-def.yml b/rules/go-func-def.yml
new file mode 100644
index 00000000000..c5bc4892307
--- /dev/null
+++ b/rules/go-func-def.yml
@@ -0,0 +1,56 @@
+# Go function definition formatting rules.
+# Based on docs/development_guidelines.md.
+#
+# These rules detect improper wrapping patterns in function definitions.
+
+# Rule: Function parameters ending with dangling comma before close paren.
+id: func-def-dangling-param-comma
+language: go
+severity: warning
+message: "Function parameters should not end with dangling comma before close paren"
+note: |
+ Per docs/development_guidelines.md: Function definition wrapping should
+ continue parameters on the next line, not leave a dangling comma.
+
+ WRONG:
+ func foo(a, b, c,
+ ) (d, error) {
+
+ RIGHT:
+ func foo(a, b,
+ c) (d, error) {
+rule:
+ kind: function_declaration
+ all:
+ # Has parameters that end with comma-newline-close-paren-open-paren (for returns)
+ - regex: ",\\s*\\n\\s*\\)\\s*\\("
+---
+# Rule: Function return types starting with open paren on its own line.
+id: func-def-dangling-return-paren
+language: go
+severity: warning
+message: "Function return types should not start with open paren on its own line"
+note: |
+ Per docs/development_guidelines.md: Return type wrapping should continue
+ on the same line, not start a new line with open paren.
+
+ WRONG:
+ func bar(a, b, c) (
+ d, error,
+ ) {
+
+ RIGHT:
+ func baz(a, b, c) (d,
+ error) {
+rule:
+ kind: function_declaration
+ all:
+ # Return type starts with close-paren-open-paren-newline
+ - regex: "\\)\\s*\\(\\s*\\n"
+# NOTE: The "multi-line function needs blank line before body" rule is disabled.
+# It's difficult to implement correctly with ast-grep because:
+# 1. The regex matches ANY block inside the function (switch, if, etc.), not
+# just the function's opening brace
+# 2. AST doesn't represent blank lines as nodes - they're only in text
+# 3. The rule would need to match the exact position of text after the {
+# This is a style hint in the guidelines, not a hard requirement.
diff --git a/sgconfig.yml b/sgconfig.yml
new file mode 100644
index 00000000000..2dd8e538b41
--- /dev/null
+++ b/sgconfig.yml
@@ -0,0 +1,2 @@
+ruleDirs:
+ - rules