rubocop-rbs_inline 1.4.0 → 1.5.0.pre.2

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/hooks/pre-commit-check.sh +29 -0
  3. data/.claude/hooks/rbs-inline.sh +97 -0
  4. data/.claude/hooks/setup.sh +28 -0
  5. data/.claude/settings.json +38 -0
  6. data/.rspec +1 -1
  7. data/.rubocop.yml +21 -1
  8. data/.vscode/settings.json +9 -1
  9. data/CHANGELOG.md +27 -0
  10. data/CLAUDE.md +66 -0
  11. data/README.md +323 -1
  12. data/Rakefile +2 -2
  13. data/config/default.yml +62 -0
  14. data/lib/rubocop/cop/rbs_inline_cops.rb +11 -0
  15. data/lib/rubocop/cop/style/rbs_inline/comment_parser.rb +121 -0
  16. data/lib/rubocop/cop/style/rbs_inline/data_class_comment_alignment.rb +127 -0
  17. data/lib/rubocop/cop/style/rbs_inline/embedded_rbs_spacing.rb +66 -0
  18. data/lib/rubocop/cop/style/rbs_inline/invalid_comment.rb +44 -27
  19. data/lib/rubocop/cop/style/rbs_inline/invalid_types.rb +23 -32
  20. data/lib/rubocop/cop/style/rbs_inline/keyword_separator.rb +57 -2
  21. data/lib/rubocop/cop/style/rbs_inline/method_comment_spacing.rb +180 -0
  22. data/lib/rubocop/cop/style/rbs_inline/missing_data_class_annotation.rb +169 -0
  23. data/lib/rubocop/cop/style/rbs_inline/missing_type_annotation.rb +293 -0
  24. data/lib/rubocop/cop/style/rbs_inline/parameters_separator.rb +22 -6
  25. data/lib/rubocop/cop/style/rbs_inline/redundant_annotation_with_skip.rb +200 -0
  26. data/lib/rubocop/cop/style/rbs_inline/redundant_type_annotation.rb +216 -0
  27. data/lib/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rb +143 -0
  28. data/lib/rubocop/cop/style/rbs_inline/source_code_helper.rb +69 -0
  29. data/lib/rubocop/cop/style/rbs_inline/unmatched_annotations.rb +8 -20
  30. data/lib/rubocop/cop/style/rbs_inline/variable_comment_spacing.rb +70 -0
  31. data/lib/rubocop/rbs_inline/plugin.rb +5 -3
  32. data/lib/rubocop/rbs_inline/version.rb +1 -1
  33. data/rbs_collection.lock.yaml +13 -13
  34. data/sig/gems/parser/parser.rbs +4 -0
  35. data/sig/rubocop/cop/style/rbs_inline/comment_parser.rbs +48 -0
  36. data/sig/rubocop/cop/style/rbs_inline/data_class_comment_alignment.rbs +71 -0
  37. data/sig/rubocop/cop/style/rbs_inline/embedded_rbs_spacing.rbs +45 -0
  38. data/sig/rubocop/cop/style/rbs_inline/invalid_comment.rbs +21 -4
  39. data/sig/rubocop/cop/style/rbs_inline/invalid_types.rbs +8 -3
  40. data/sig/rubocop/cop/style/rbs_inline/keyword_separator.rbs +33 -0
  41. data/sig/rubocop/cop/style/rbs_inline/method_comment_spacing.rbs +107 -0
  42. data/sig/rubocop/cop/style/rbs_inline/missing_data_class_annotation.rbs +82 -0
  43. data/sig/rubocop/cop/style/rbs_inline/missing_type_annotation.rbs +185 -0
  44. data/sig/rubocop/cop/style/rbs_inline/parameters_separator.rbs +11 -1
  45. data/sig/rubocop/cop/style/rbs_inline/redundant_annotation_with_skip.rbs +116 -0
  46. data/sig/rubocop/cop/style/rbs_inline/redundant_argument_type.rbs +85 -0
  47. data/sig/rubocop/cop/style/rbs_inline/redundant_return_type.rbs +109 -0
  48. data/sig/rubocop/cop/style/rbs_inline/redundant_type_annotation.rbs +140 -0
  49. data/sig/rubocop/cop/style/rbs_inline/require_rbs_inline_comment.rbs +79 -0
  50. data/sig/rubocop/cop/style/rbs_inline/source_code_helper.rbs +43 -0
  51. data/sig/rubocop/cop/style/rbs_inline/unmatched_annotations.rbs +4 -7
  52. data/sig/rubocop/cop/style/rbs_inline/variable_comment_spacing.rbs +52 -0
  53. data/sig/rubocop/rbs_inline/plugin.rbs +7 -3
  54. metadata +37 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28c10d4c13563cfc463decbe536ccbb53c0dab6102fb0c3f439b0693a03e0e6b
4
- data.tar.gz: cc3e878fd7e43ea9e5ec255c355ada40a946a39381c6dc6d66c74450bde97ad7
3
+ metadata.gz: 813f81c0980296d50e92c6a928f3ac51e3954748095a1e0dd6117cdcf77a8166
4
+ data.tar.gz: '029b0e05c922841def3501e57587045660c4d0f05752dba974797f7215661b62'
5
5
  SHA512:
6
- metadata.gz: 0bbb06a5a7217f4a9858eefba6e3dac8e07c46363c8406b47cccbda6a66eda54710dd63b34c990eca2941e41bce1a2f73565e0c2853839aacf8809388f7c031e
7
- data.tar.gz: b4733af9878300b883cbe5e8919d914ecfa003416135e9c747bb4c22380e6d938551ff790ed6584003f17e4bea4771318beea62be91937b857d858e1cd889191
6
+ metadata.gz: 2768b2232009f4c70366981b7ffc47ef55edef17f6938f31d0740a645189a71fea2666e64edaf005cb27489ea18f2038f80c917240bc861fa8b60672e2286dbc
7
+ data.tar.gz: 42191af687cb627862f2ee617579df7932c65b656d35c7c4651453dc2c58106f28f73b2794107c3eb99a4d66bab141b43015072493bd19b60e3a8bc27f7d4f76
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+
3
+ # Hook input is JSON from stdin
4
+ input=$(cat)
5
+ tool_name=$(echo "$input" | jq -r '.tool_name')
6
+ command=$(echo "$input" | jq -r '.tool_input.command // ""')
7
+
8
+ # Only run for git commit commands
9
+ if [[ "$tool_name" != "Bash" ]] || [[ ! "$command" =~ git[[:space:]]+(commit|cherry-pick|merge|rebase) ]]; then
10
+ exit 0
11
+ fi
12
+
13
+ cd "$CLAUDE_PROJECT_DIR" || exit 1
14
+
15
+ echo "Running pre-commit checks..." >&2
16
+
17
+ # Generate RBS and run all checks
18
+ if ! "$CLAUDE_PROJECT_DIR/bin/rbs-inline" --opt-out --output=sig/ lib/ >&2; then
19
+ echo "Error: RBS generation failed" >&2
20
+ exit 2
21
+ fi
22
+
23
+ if ! "$CLAUDE_PROJECT_DIR/bin/rake" >&2; then
24
+ echo "Error: rake checks failed" >&2
25
+ exit 2
26
+ fi
27
+
28
+ echo "All checks passed!" >&2
29
+ exit 0
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+
3
+ # Hook input is JSON from stdin
4
+ input=$(cat)
5
+ tool_name=$(echo "$input" | jq -r '.tool_name')
6
+
7
+ cd "$CLAUDE_PROJECT_DIR" || exit 1
8
+
9
+ # Handle Edit or Write tools
10
+ if [[ "$tool_name" == "Edit" || "$tool_name" == "Write" ]]; then
11
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
12
+
13
+ if [[ ! "$file_path" =~ \.rb$ ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ if [[ ! "$file_path" =~ /lib/ ]]; then
18
+ exit 0
19
+ fi
20
+
21
+ echo "Running rbs-inline for $file_path..." >&2
22
+
23
+ if ! "$CLAUDE_PROJECT_DIR/bin/rbs-inline" --opt-out --output=sig/ "$file_path" >&2; then
24
+ echo "Warning: RBS generation failed for $file_path" >&2
25
+ exit 0
26
+ fi
27
+
28
+ echo "RBS generation completed." >&2
29
+ exit 0
30
+ fi
31
+
32
+ # Handle Bash tool for mv command
33
+ if [[ "$tool_name" == "Bash" ]]; then
34
+ command=$(echo "$input" | jq -r '.tool_input.command // ""')
35
+
36
+ # Check if this is a mv command
37
+ if [[ ! "$command" =~ ^[[:space:]]*(mv|git\ mv)[[:space:]] ]]; then
38
+ exit 0
39
+ fi
40
+
41
+ # Extract source and destination paths from mv command
42
+ # Handle common patterns: mv src dest, git mv src dest
43
+ # Remove the mv/git mv prefix and get the paths
44
+ paths=$(echo "$command" | sed -E 's/^[[:space:]]*(git[[:space:]]+)?mv[[:space:]]+//')
45
+
46
+ # Split into source and destination (simple case, space-separated)
47
+ # This handles: mv old.rb new.rb, mv old.rb dir/
48
+ source_path=$(echo "$paths" | awk '{print $1}')
49
+ dest_path=$(echo "$paths" | awk '{print $2}')
50
+
51
+ # Check if source was a .rb file in lib/
52
+ if [[ ! "$source_path" =~ \.rb$ ]] || [[ ! "$source_path" =~ lib/ ]]; then
53
+ exit 0
54
+ fi
55
+
56
+ echo "Detected mv of Ruby file in lib/: $source_path -> $dest_path" >&2
57
+
58
+ # Calculate the corresponding .rbs file path for the source
59
+ # Convert lib/path/to/file.rb to sig/path/to/file.rbs
60
+ source_rbs=$(echo "$source_path" | sed -E 's|^(.*/)?lib/|sig/|; s|\.rb$|.rbs|')
61
+
62
+ # Remove the old .rbs file if it exists
63
+ if [[ -f "$source_rbs" ]]; then
64
+ echo "Removing old RBS file: $source_rbs" >&2
65
+ rm -f "$source_rbs"
66
+ fi
67
+
68
+ # Determine the new .rb file path
69
+ # If dest is a directory, append the source filename
70
+ if [[ -d "$dest_path" ]]; then
71
+ dest_file="$dest_path/$(basename "$source_path")"
72
+ else
73
+ dest_file="$dest_path"
74
+ fi
75
+
76
+ # Check if the destination is in lib/
77
+ if [[ ! "$dest_file" =~ lib/ ]]; then
78
+ echo "Destination is not in lib/, skipping RBS generation" >&2
79
+ exit 0
80
+ fi
81
+
82
+ # Generate RBS for the new file
83
+ if [[ -f "$dest_file" ]]; then
84
+ echo "Running rbs-inline for $dest_file..." >&2
85
+
86
+ if ! "$CLAUDE_PROJECT_DIR/bin/rbs-inline" --opt-out --output=sig/ "$dest_file" >&2; then
87
+ echo "Warning: RBS generation failed for $dest_file" >&2
88
+ exit 0
89
+ fi
90
+
91
+ echo "RBS generation completed." >&2
92
+ fi
93
+
94
+ exit 0
95
+ fi
96
+
97
+ exit 0
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+
3
+ # Initialize rbenv for Claude Code on the Web
4
+ eval "$(rbenv init -)"
5
+
6
+ # Install dependencies
7
+ # Note: Bundler 4.0.3 has a bug with Ruby 3.3.x causing CGI class variable errors.
8
+ # Install and use Bundler 2.x to avoid this issue.
9
+ gem install bundler -v 2.7.2 --no-document
10
+ bundle _2.7.2_ install
11
+
12
+ # Install dependencies for each gem directory (directories with .gemspec files)
13
+ for gemspec in "$CLAUDE_PROJECT_DIR"/*/*.gemspec; do
14
+ if [[ -f "$gemspec" ]]; then
15
+ gem_dir=$(dirname "$gemspec")
16
+ if [[ -f "$gem_dir/Gemfile" ]]; then
17
+ echo "Installing dependencies for $(basename "$gem_dir")..."
18
+ (cd "$gem_dir" && bundle _2.7.2_ install)
19
+ fi
20
+ fi
21
+ done
22
+
23
+ # Persist environment for subsequent commands
24
+ if [ -n "$CLAUDE_ENV_FILE" ]; then
25
+ echo 'eval "$(rbenv init -)"' >> "$CLAUDE_ENV_FILE"
26
+ fi
27
+
28
+ exit 0
@@ -0,0 +1,38 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/setup.sh",
10
+ "timeout": 300
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "PreToolUse": [
16
+ {
17
+ "matcher": "Bash",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pre-commit-check.sh"
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PostToolUse": [
27
+ {
28
+ "matcher": "Edit|Write|Bash",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/rbs-inline.sh"
33
+ }
34
+ ]
35
+ }
36
+ ]
37
+ }
38
+ }
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
- --format documentation
1
+ --format progress
2
2
  --color
3
3
  --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,10 +1,17 @@
1
1
  plugins:
2
2
  - rubocop-rake
3
3
  - rubocop-rspec
4
+ - rubocop-rbs_inline
4
5
 
5
6
  AllCops:
6
7
  NewCops: enable
7
- TargetRubyVersion: 3.1
8
+ TargetRubyVersion: 3.3
9
+ Exclude:
10
+ - bin/**/*
11
+ - vendor/**/*
12
+
13
+ Layout/LineLength:
14
+ Max: 120
8
15
 
9
16
  Metrics/AbcSize:
10
17
  Max: 20
@@ -29,9 +36,22 @@ RSpec/NestedGroups:
29
36
  Style/Documentation:
30
37
  Enabled: false
31
38
 
39
+ Style/HashSyntax:
40
+ EnforcedShorthandSyntax: always
41
+
32
42
  # for RBS::Inline
33
43
  Layout/LeadingCommentSpace:
34
44
  Enabled: false
35
45
 
36
46
  Style/CommentedKeyword:
37
47
  Enabled: false
48
+
49
+ # rubocop-rbs_inline configuration
50
+ Style/RbsInline/MissingTypeAnnotation:
51
+ EnforcedStyle: doc_style_and_return_annotation
52
+
53
+ Style/RbsInline/RedundantTypeAnnotation:
54
+ EnforcedStyle: doc_style_and_return_annotation
55
+
56
+ Style/RbsInline/RequireRbsInlineComment:
57
+ EnforcedStyle: never
@@ -1,13 +1,21 @@
1
1
  {
2
2
  "cSpell.words": [
3
+ "bindir",
3
4
  "blockarg",
4
5
  "Ivar",
6
+ "KOMIYA",
5
7
  "kwarg",
6
8
  "kwoptarg",
7
9
  "kwrestarg",
8
10
  "optarg",
11
+ "popen",
12
+ "readlines",
9
13
  "restarg",
10
- "strscan"
14
+ "rubocop",
15
+ "rubygems",
16
+ "strscan",
17
+ "Takeshi",
18
+ "tk0miya"
11
19
  ],
12
20
  "rbs-helper.rbs-inline-on-save": true,
13
21
  "rbs-helper.rbs-inline-signature-directory": "sig/"
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## 1.5.0 (unreleased)
4
+
5
+ ### New Cops
6
+
7
+ - **Style/RbsInline/RedundantAnnotationWithSkip**: Warns when type annotations (`#:` method type signatures, `# @rbs` method types, parameter annotations, return type annotations, or trailing inline types) are present alongside `# @rbs skip` or `# @rbs override`. These directives skip RBS generation, making any additional type annotations redundant. Supports unsafe autocorrect.
8
+ - **Style/RbsInline/RedundantReturnType**: Warns when both a `# @rbs return` comment and a `#:` annotation comment specify the return type for the same method. The `EnforcedStyle` option accepts `inline_comment` (prefer `#:`) or `rbs_return_comment` (prefer `# @rbs return`). Supports safe autocorrect.
9
+ - **Style/RbsInline/RedundantArgumentType**: Warns when both a `# @rbs param` comment and a `#:` annotation comment specify the argument type for the same method. The `EnforcedStyle` option accepts `annotation_comment` or `rbs_param_comment` (default). Supports autocorrect when `annotation_comment` style is preferred.
10
+ - **Style/RbsInline/MissingTypeAnnotation**: Warns when a method definition has no type annotation. The `Visibility` option narrows the target methods by visibility (default: `all`).
11
+ - **Style/RbsInline/RequireRbsInlineComment**: Enforces the presence or absence of a `# rbs_inline:` magic comment. The `EnforcedStyle` option accepts `always` (default, requires the comment) or `never` (forbids the comment).
12
+ - **Style/RbsInline/EmbeddedRbsSpacing**: Warns when a `@rbs!` embedded RBS comment block is not followed by a blank line. Supports autocorrect.
13
+ - **Style/RbsInline/VariableCommentSpacing**: Warns when a `@rbs` variable comment (`@ivar`, `@@cvar`, `self.@ivar`) is not followed by a blank line. Supports autocorrect.
14
+ - **Style/RbsInline/MethodCommentSpacing**: Warns when a method-related `@rbs` annotation (`param`, `return`, `&block`, `override`, `skip`, etc.) is not placed immediately before the method definition it describes.
15
+ - **Style/RbsInline/MissingDataClassAnnotation**: Warns when an attribute passed to `Data.define` does not have a trailing `#:` inline type annotation. Supports autocorrect.
16
+ - **Style/RbsInline/DataClassCommentAlignment**: Warns when the `#:` inline type annotation comments in a multiline `Data.define` block are not aligned to the same column. Supports autocorrect.
17
+
18
+ ### Enhancements
19
+
20
+ - **InvalidComment**: Added autocorrect support.
21
+ - **KeywordSeparator**: Added autocorrect support.
22
+ - **ParametersSeparator**: Added autocorrect support.
23
+
24
+ ### Dependency Updates
25
+
26
+ - Updated rbs-inline to 0.13.0.
27
+ - Raised minimum Ruby version to 3.3.0.
data/CLAUDE.md ADDED
@@ -0,0 +1,66 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ rubocop-rbs_inline is a RuboCop extension gem that provides cops for validating RBS::Inline type annotation comments in Ruby code. It checks syntax, formatting, and redundancy of `#:` and `# @rbs` style annotations.
8
+
9
+ ## Common Commands
10
+
11
+ ```bash
12
+ # Run tests
13
+ bin/rspec
14
+ bin/rspec spec/rubocop/cop/style/rbs_inline/invalid_comment_spec.rb # single file
15
+ bin/rspec spec/rubocop/cop/style/rbs_inline/invalid_comment_spec.rb:8 # single example
16
+
17
+ # Lint
18
+ bin/rake rubocop
19
+ bin/rake rubocop:autocorrect # safe autocorrect
20
+ bin/rake rubocop:autocorrect_all # all autocorrect
21
+
22
+ # Type check
23
+ bin/rake rbs:check # runs steep check
24
+
25
+ # Default rake task (runs specs, rubocop, and type check)
26
+ bin/rake
27
+
28
+ # Generate a new cop
29
+ bin/rake 'new_cop[Style/RbsInline/CopName]'
30
+ ```
31
+
32
+ ## Architecture
33
+
34
+ ### Cop Structure
35
+
36
+ All cops live under `RuboCop::Cop::Style::RbsInline` namespace in `lib/rubocop/cop/style/rbs_inline/`. Each cop validates a different aspect of RBS::Inline annotations:
37
+
38
+ - **InvalidComment** - Validates `#:` and `# @rbs` comment syntax
39
+ - **InvalidTypes** - Validates RBS type syntax in annotations
40
+ - **KeywordSeparator** - Ensures keywords like `module-self` aren't followed by `:`
41
+ - **ParametersSeparator** - Ensures parameter annotations use `:` separator
42
+ - **RedundantArgumentType** - Detects redundant argument type specs (configurable style)
43
+ - **RedundantReturnType** - Detects redundant return type specs (3 style options)
44
+ - **UnmatchedAnnotations** - Ensures annotation parameters match actual method parameters
45
+
46
+ ### Shared CommentParser Module
47
+
48
+ `comment_parser.rb` is a module mixed into cops that need to parse RBS::Inline annotations. It uses `RBS::Inline::AnnotationParser` and Prism to parse comments, and provides helpers for finding leading annotations, inline comments, and return annotations relative to method definitions.
49
+
50
+ ### Plugin System
51
+
52
+ The gem integrates with RuboCop via LintRoller (`lib/rubocop/rbs_inline/plugin.rb`). Default cop configuration is in `config/default.yml`.
53
+
54
+ ### Type Signatures
55
+
56
+ RBS type signatures for all source files are maintained in `sig/` directory. The project uses Steep for static type checking, configured via `Steepfile`.
57
+
58
+ ### Testing Pattern
59
+
60
+ Tests use RuboCop's RSpec support helpers (`expect_offense` / `expect_no_offenses`). Test files mirror the cop file structure under `spec/rubocop/cop/style/rbs_inline/`.
61
+
62
+ ## Code Style Notes
63
+
64
+ - `Layout/LeadingCommentSpace` and `Style/CommentedKeyword` are disabled because RBS::Inline `#:` comments violate these rules by design.
65
+ - Max line length: 120 characters.
66
+ - The codebase itself uses RBS::Inline annotations (`#:` and `# @rbs` comments) for type definitions.